直接GRANT EXECUTE ON PACKAGE不够用,因AUTHID DEFINER模式下角色权限不生效,包内所有依赖对象(表、视图、序列、系统包等)必须向包所有者显式授予直接权限,否则运行时报ORA-00942或PLS-00201。

为什么直接 GRANT EXECUTE ON PACKAGE 不够用
因为 Oracle 的 Package 默认是 AUTHID DEFINER(定义者权限),但若包体里调用了其他对象(比如视图、序列、DBMS_SCHEDULER 过程),而这些对象的权限是通过角色授予的,运行时就会报 ORA-00942: table or view does not exist 或 PLS-00201: identifier must be declared。根本原因:角色权限在定义者权限上下文中**不生效**,只认直接授予(direct grant)的权限。
必须显式授予 Package 所依赖的所有底层对象权限
一个 Package 能跑通,不只取决于你有没有 EXECUTE 权限,更取决于它内部访问的所有对象——表、视图、序列、其他 Package、系统包(如 DBMS_OUTPUT、DBMS_SCHEDULER)是否已对 Package 所属 Schema **直接授权**。
- 查包依赖:
SELECT referenced_owner, referenced_name, referenced_type FROM all_dependencies WHERE owner = 'PKG_OWNER' AND name = 'MY_PKG' AND type = 'PACKAGE'; - 如果依赖
HR.EMPLOYEES,则必须执行:GRANT SELECT ON hr.employees TO pkg_owner;(不能通过角色授) - 如果包里调用了
DBMS_SCHEDULER.CREATE_JOB,需确认pkg_owner已被直接授予CREATE JOB系统权限(不是通过 CONNECT 或 RESOURCE 角色) - 若包中引用了序列
seq_log_id,且用到nextval,必须:GRANT SELECT ON seq_log_id TO pkg_owner;
目标用户只能有 EXECUTE ON PACKAGE,不能有 CREATE SESSION 以外的其他系统权限
很多人顺手加 GRANT CONNECT TO app_user;,结果意外开了 CREATE TABLE、CREATE VIEW 等高危能力。最小化组合只有两个:
CREATE USER app_user IDENTIFIED BY "xxx";GRANT CREATE SESSION TO app_user;-
GRANT EXECUTE ON pkg_owner.my_pkg TO app_user;(逐个包、逐个过程,不可批量走角色)
绝对不要:GRANT EXECUTE ANY PROCEDURE TO app_user,也别把 EXECUTE 权限塞进自定义角色再授给用户——角色在 AUTHID DEFINER 包里完全失效。
验证时必须用真实连接 + 匿名块调用
别只查 USER_TAB_PRIVS 就认为 OK。真正有效的验证方式是切换到该用户,执行一段调用包内过程的匿名块:
CONNECT app_user/xxx BEGIN pkg_owner.my_pkg.do_something(); END;
如果报错,重点看错误栈第一行:是 PLS-00201(找不到对象)还是 ORA-00942(无访问权限),前者说明包里引用了未声明的对象(比如漏写 schema 前缀),后者说明依赖对象缺 direct grant。最容易被忽略的是:包里用到的同义词(synonym)指向的对象,其权限也要直授给包所有者,而不是同义词创建者。











