我创建了一个包,它在同一页面内的SELECT语句中执行我的函数:
CREATE OR REPLACE PACKAGE p
AUTHID DEFINER
IS
FUNCTION f
RETURN NUMBER;
END;
/
CREATE OR REPLACE PACKAGE BODY p
IS
FUNCTION ff RETURN NUMBER
IS
BEGIN
RETURN 73;
END;
FUNCTION f RETURN NUMBER
IS
l_number NUMBER;
BEGIN
SELECT 42 INTO l_number
FROM DUAL
WHERE ff () = 73;
RETURN l_number;
END;
END;
/
BEGIN
DBMS_OUTPUT.put_line (p.f);
END;
/
但是当我尝试执行该函数时,我得到了PLS-00231编译错误:
BEGIN
dbms_output.put_line (P.F);
END;
/
PLS-00231: function 'FF' may not be used in SQL
该功能在那里宣布。它不执行任何非查询DML。它在标头中没有任何PL / SQL特定的数据类型。
为什么SQL不能使用/看到它?
答案 0 :(得分:4)
这是底线:
如果要从SQL语句中调用函数,则必须在模式级别(CREATE FUNCTION)声明或在包的规范中定义。即使您的SQL语句位于与调用函数相同的包中的子程序内,也是如此。
因此,如果我按照以下方式更改包规范,公开以前的私有函数,一切都很好:
CREATE OR REPLACE PACKAGE p AUTHID DEFINER
IS
FUNCTION f RETURN NUMBER;
FUNCTION ff RETURN NUMBER;
END;
/
有趣的是,请注意,您不必在静态SQL语句中使用包名限定函数的名称。 PL / SQL编译器在将语句传递给SQL引擎之前对其进行排序。
但是,如果动态执行SQL,则需要包名称,如:
FUNCTION f RETURN NUMBER
IS
l_number NUMBER;
BEGIN
EXECUTE IMMEDIATE
'SELECT 42 FROM DUAL WHERE p.ff () = 73'
INTO l_number;
RETURN l_number;
END;