ORA-01031在存储过程中报错主因是定义者权限模式下角色权限失效,需直接授予系统权限(如GRANT CREATE TABLE TO user)或改用AUTHID CURRENT_USER;同时须检查SESSION_PRIVS、SESSION_ROLES及配套权限。

ORA-01031 报错在存储过程中出现,基本不是“没权限”,而是权限没在 PL/SQL 运行时上下文中生效——Oracle 默认用 AUTHID DEFINER(定义者权限),此时角色权限(如 DBA、RESOURCE)全部失效,只认直接授予的系统权限或对象权限。
为什么直接执行 DDL 成功,进存储过程就报 ORA-01031?
因为会话里通过角色获得的 CREATE TABLE 权限,在匿名块中可用;但一旦封装进存储过程,默认以定义者身份运行,角色被忽略。哪怕你查 SESSION_ROLES 看到 DBA 在里面,过程里照样不可用。
- 直接执行
CREATE TABLE t1(id NUMBER);→ 依赖角色,成功 - 写进过程:
EXECUTE IMMEDIATE 'CREATE TABLE t1(id NUMBER)';→ 角色失效,报 ORA-01031 - 根本原因:PL/SQL 编译和运行阶段都强制检查“直接授权”,不走角色链
包或过程调用跨 schema 对象时权限断在哪?
常见误判是“已经给了包 EXECUTE 权限”,但真正卡住的是包体内部访问的底层对象——比如 pkg_report 查询了 hr.employees,那光授 EXECUTE ON pkg_report 不够,还得确保 hr.employees 的 SELECT 权限已显式授予调用者,且 hr 授权时用了 WITH GRANT OPTION(否则包所有者无法转授)。
- 错误授权:
GRANT SELECT ON hr.employees TO app;→ 包内调用仍失败 - 正确授权:
GRANT SELECT ON hr.employees TO app WITH GRANT OPTION; - 私有子程序不能单独授权,必须靠整个包的
EXECUTE权限覆盖 - 用
SELECT * FROM ALL_DEPENDENCIES WHERE NAME = 'PKG_REPORT' AND REFERENCED_OWNER = 'HR';顺藤摸瓜查依赖
怎么快速定位当前会话缺哪类权限?
别猜,直接查两个视图:
- 查
SELECT * FROM SESSION_PRIVS;→ 看CREATE TABLE、SELECT ANY TABLE等是否真实存在(不是“被角色包含”,而是“已激活”) - 查
SELECT * FROM SESSION_ROLES;→ 如果为空,说明连接后根本没启用任何角色(JDBC/cx_Oracle 默认不自动SET ROLE) - 查
SELECT USERNAME, DEFAULT_TABLESPACE, ACCOUNT_STATUS FROM DBA_USERS WHERE USERNAME = SYS_CONTEXT('USERENV', 'SESSION_USER');→ 排除默认表空间未配、账户锁定等干扰项 - 对动态 SQL 报错,优先怀疑系统权限(如
CREATE ANY TABLE)没直授,而不是对象权限
最常被跳过的动作,是在应用连接 Oracle 后忘了 SET ROLE ALL; 或显式启用带密码的角色;而最隐蔽的坑,是跨 schema 授权时漏掉 WITH GRANT OPTION,导致权限链在第二层就断了。


















