Yourfunction_private
仅在包体中声明,因此其范围仅限于包中的其他过程。因此,它必须符合那些调用过程的纯度级别,否则编译器将抛出异常。
比较这个安全声明(注意,我已经扩展了 的纯度function_public
)......
SQL> CREATE OR REPLACE PACKAGE PRAGMA_TEST AS
2 FUNCTION function_public(x IN VARCHAR2) RETURN VARCHAR2;
3 PRAGMA RESTRICT_REFERENCES( function_public, WNDS, WNPS, RNDS);
4 END PRAGMA_TEST;
5 /
Package created.
SQL> CREATE OR REPLACE PACKAGE BODY PRAGMA_TEST AS
2 FUNCTION function_private(y IN VARCHAR2) RETURN VARCHAR2 IS
3 BEGIN
4 return 'no harm done';
5 END;
6
7 FUNCTION function_public(x IN VARCHAR2) RETURN VARCHAR2 IS
8 BEGIN
9 return function_private(x);
10 END;
11 END PRAGMA_TEST;
12 /
Package body created.
SQL>
……有了这个不安全的……
SQL> CREATE OR REPLACE PACKAGE BODY PRAGMA_TEST AS
2 FUNCTION function_private(y IN VARCHAR2) RETURN VARCHAR2 IS
3 rv varchar2(1);
4 BEGIN
5 select dummy into rv from dual;
6 return rv;
7 END;
8
9 FUNCTION function_public(x IN VARCHAR2) RETURN VARCHAR2 IS
10 BEGIN
11 return function_private(x);
12 END;
13 END PRAGMA_TEST;
14 /
Warning: Package Body created with compilation errors.
SQL> sho err
Errors for PACKAGE BODY PRAGMA_TEST:
LINE/COL ERROR
-------- -----------------------------------------------------------------
9/3 PLS-00452: Subprogram 'FUNCTION_PUBLIC' violates its associated
pragma
SQL>
RESTRICTS_REFERENCES pragma 的要点是包规范中声明的过程可以被其他包使用,甚至是 SQL 语句,由其他用户(模式)拥有或执行,这些用户可能无法访问我们的包主体的源代码。编译指示是我们向他们保证将我们的代码合并到他们的代码中的影响的一种方法。这就是为什么必须在规范中声明 pragma 的原因,因为当我们将包上的 EXECUTE 授予另一个用户时,这是代码中唯一暴露的部分。
编辑
啊,现在看到您修改后的代码示例,我了解您要做什么。它不会,不会,不能工作。我们只允许在 SQL 中使用 spec = public functions 中声明的打包函数。SQL 是用 SQL*Plus 编写的,还是用另一个封装过程编码的,都没有关系。错误堆栈中的原因很清楚:
SQL> CREATE OR REPLACE PACKAGE PRAGMA_TEST AS
2 FUNCTION function_public(x IN VARCHAR2) RETURN VARCHAR2;
3 PRAGMA RESTRICT_REFERENCES( function_public, WNDS, WNPS);
4 END PRAGMA_TEST;
5 /
Package created.
SQL> CREATE OR REPLACE PACKAGE BODY PRAGMA_TEST AS
2 FUNCTION function_private(y IN VARCHAR2) RETURN VARCHAR2 IS
3 rv varchar2(1);
4 BEGIN
5 select dummy into rv from dual;
6 return rv;
7 END;
8
9 FUNCTION function_public(x IN VARCHAR2) RETURN VARCHAR2 IS
10 rv varchar2(1);
11 BEGIN
12 select function_private(x) into rv from dual;
13 return rv;
14 END;
15 END PRAGMA_TEST;
16 /
Warning: Package Body created with compilation errors.
SQL> sho err
Errors for PACKAGE BODY PRAGMA_TEST:
LINE/COL ERROR
-------- -----------------------------------------------------------------
12/6 PL/SQL: SQL Statement ignored
12/13 PL/SQL: ORA-00904: : invalid identifier
12/13 PLS-00231: function 'FUNCTION_PRIVATE' may not be used in SQL
SQL>
编译器崩溃ORA-00904: invalid identifier
是因为该函数未在规范中声明;它与纯度水平无关,
关于范围的说明
PL/SQL的作用域规则并不完全一致:我们可以在打包的 SQL 语句中使用私有变量:
SQL> CREATE OR REPLACE PACKAGE BODY PRAGMA_TEST AS
2
3 gv constant varchar2(8) := 'global';
4
5 FUNCTION function_private(y IN VARCHAR2) RETURN VARCHAR2 IS
6 rv varchar2(1);
7 BEGIN
8 select dummy into rv from dual;
9 return rv;
10 END;
11
12 FUNCTION function_public(x IN VARCHAR2) RETURN VARCHAR2 IS
13 rv varchar2(10);
14 BEGIN
15 select gv||'+'||dummy into rv from dual;
16 return rv;
17 END;
18 END PRAGMA_TEST;
19 /
Package body created.
SQL>
如果我们想在 SQL 语句中使用 wm 必须在规范中声明的函数和类型。