【IT168 技术文档】调用者权限存储过程的权限使用上和定义者权限存储过程有所差别。这个差异在于角色是否生效。
对于定义者权限存储过程,角色是无效的,如果需要在存储过程中使用某些权限,那么这些权限必须是直接授权给用户或者PUBLIC的,而不能是通过角色获得的权限。
而调用者权限则不同。需要注意的是,并不是说对于调用者权限存储过程而言,角色一直是有效的。在调用者权限存储过程的编译时刻,权限的限制和定义者权限存储过程没有什么区别,都是角色无效的。只有在调用者权限存储过程在执行时刻,存储过程当前的调用者的角色权限是可以生效的。
根据这一点,可以在编写调用者权限过程时,通过使用动态SQL来避免直接授权,而将权限的检查延后至运行时,而运行时角色是生效的,这样可以避免权限带来的问题。
SQL> CREATE OR REPLACE PROCEDURE P_TEST AUTHID CURRENT_USER AS
2 V_DBNAME VARCHAR2(9);
3 BEGIN
4 SELECT NAME INTO V_DBNAME FROM V$DATABASE;
5 END;
6 /
警告: 创建的过程带有编译错误。
SQL> SHOW ERR
PROCEDURE P_TEST 出现错误:
LINE/COL ERROR
-------- ------------------
4/1 PL/SQL: SQL Statement ignored
4/32 PL/SQL: ORA-00942: 表或视图不存在
SQL> CREATE OR REPLACE PROCEDURE P_TEST AUTHID CURRENT_USER AS
2 V_DBNAME VARCHAR2(9);
3 BEGIN
4 EXECUTE IMMEDIATE 'SELECT NAME FROM V$DATABASE' INTO V_DBNAME;
5 END;
6 /
过程已创建。
SQL> EXEC P_TEST
PL/SQL 过程已成功完成。
需要注意的是,这种方法虽然可以避免直接授权,但是由于采用了动态SQL,也使得存储过程本身的优点无法体现出来。如果是需要经常运行的过程,没有必要为了图一时的省事而带来性能上的负担。