编译成功但调用报ORA-01031或PLS-00201,本质是Oracle权限校验分两层:编译时检查定义者对静态SQL对象的直接权限(角色权限无效),调用时按AUTHID模式检查当前会话实际可用权限(需SESSION_ROLES非空且SESSION_TAB_PRIVS含对应显式授权)。

编译成功但调用报ORA-01031或PLS-00201,本质是权限校验时机不同
Oracle对PL/SQL对象的权限检查分两层:编译时只查定义者(OWNER)是否有**静态SQL中所有对象的直接权限**;而调用时,若包体里有动态SQL或跨用户访问,实际执行那条语句时才触发权限校验——此时检查的是**当前会话的实际可用权限**,不是定义者的角色权限。
常见表现:CREATE OR REPLACE PACKAGE BODY 成功,EXEC pkg.proc 却报 ORA-01031 或 PLS-00201: identifier 'XXX' must be declared(后者常因权限不足导致对象不可见)。
- 编译阶段只看定义者是否显式拥有表/视图/序列等的
SELECT、INSERT等权限,角色授予的权限在编译时不生效 - 调用阶段若包体中含
EXECUTE IMMEDIATE或引用了其他用户对象(如SELECT * FROM scott.emp),则运行时按调用者身份查权限(AUTHID CURRENT_USER)或仍按定义者查(AUTHID DEFINER),但此时角色权限默认不激活 - 即使定义者有
DBA角色,只要没显式GRANT SELECT ON scott.emp TO pkg_owner,编译就可能失败;而如果编译过了,调用时仍可能因调用者缺权限或角色未启用而崩
查 SESSION_ROLES 和 SESSION_TAB_PRIVS 才知道权限“活没活”
别只查 DBA_ROLE_PRIVS 或 DBA_TAB_PRIVS——它们只说明“授过”,不反映当前会话真实能用哪些权限。
登录后立刻执行:
-
SELECT * FROM SESSION_ROLES;—— 如果返回空,说明你虽被授了RESOURCE或SELECT_CATALOG_ROLE,但没启用。需手动SET ROLE ALL或SET ROLE role_name -
SELECT * FROM SESSION_TAB_PRIVS WHERE TABLE_NAME = 'EMP' AND OWNER = 'SCOTT';—— 这里只列**当前会话显式获得的对象权限**,角色间接带来的不会出现 - 若调用包用的是
AUTHID CURRENT_USER,以上两查必须非空且含对应权限;若是AUTHID DEFINER,则要查包属主的SESSION_TAB_PRIVS,而非调用者的
GRANT EXECUTE ON pkg TO user 不等于“能安全调用”
授执行权只是第一步。真正卡住的,往往是包体内部 SQL 所依赖的底层对象权限。
- 假设
scott.pkg里有INSERT INTO hr.departments,你给a_user授了EXECUTE ON scott.pkg,但scott自己没被GRANT INSERT ON hr.departments TO scott过,调用时仍报ORA-01031 - 同理,如果包里用了同义词(
CREATE SYNONYM my_emp FOR hr.employees),权限校验仍穿透到hr.employees,且要求scott显式有SELECT权限,不能靠CONNECT或RESOURCE角色 - 用
AUTHID CURRENT_USER可绕开定义者权限问题,但调用者必须自己有所有被访问对象的权限,且其SESSION_ROLES已启用——这点在 JDBC/Navicat 连接中极易被忽略
Navicat、JDBC 调用失败,大概率是连接上下文没激活角色
图形工具和应用连接默认不启用角色,哪怕你在 SQL*Plus 里 SET ROLE ALL 测试成功,换工具就挂。
- Navicat 执行 DDL/DML 前,先运行
SET ROLE ALL再调用包,否则SESSION_ROLES为空 - JDBC 连接字符串加
currentSchema=xxx不影响权限模型;真正起作用的是连接后第一句是否执行SET ROLE - 某些驱动(如 ojdbc8)支持
oracle.jdbc.defaultRowPrefetch等参数,但没提供自动启用角色的开关——必须在业务代码里显式执行 - 最稳的做法:把
SET ROLE ALL写进应用初始化 SQL,或改用GRANT显式权限替代角色依赖
真正麻烦的不是“没授权”,而是权限链在不同上下文里断得悄无声息——编译时一个世界,调用时另一个世界,连错误提示都未必指向根因。


















