授权后仍报 ora-01031或ora-00942,主因是权限未生效:角色未启用、对象权限未显式授予、或校验时机不当;pl/sql中角色权限默认无效,需查session_roles、session_privs、session_tab_privs确认实际可用权限。

授权后仍报 ORA-01031 或 ORA-00942,大概率不是没授,而是权限没“活”起来——角色未启用、权限未显式授予、或校验时机不对。
为什么 GRANT 了还是没用?看权限是否真生效
Oracle 的权限检查分静态(编译时)和动态(运行时),且角色权限在 PL/SQL 中默认不生效。光查 DBA_ROLE_PRIVS 看谁被授了什么角色,没用;得确认当前会话实际能用哪些权限。
- 运行
SELECT * FROM SESSION_ROLES;—— 如果返回空,说明你虽有角色,但没启用(SET ROLE ALL或ALTER USER ... DEFAULT ROLE ALL) - 运行
SELECT * FROM SESSION_PRIVS;—— 这里只列直接授予用户的系统权限,不包含角色间接带来的权限 - 运行
SELECT * FROM SESSION_TAB_PRIVS;—— 查当前会话对哪些表/视图有对象权限(注意:仅限显式GRANT,非角色授予)
AUTHID DEFINER 存储过程编译就失败,怎么办
默认的 AUTHID DEFINER 模式会在编译阶段就检查定义者(即过程属主)是否有底层对象权限,而不是等运行时。哪怕你只是写了 SELECT * FROM hr.employees,只要 hr 没显式执行过 GRANT SELECT ON employees TO owner_user,编译直接报 ORA-00942。
- 角色权限(如
RESOURCE)在DEFINER模式下完全无效,必须显式授对象权限 -
SYNONYM或VIEW不绕过校验,权限要求仍穿透到基表 - 跨 schema 操作(如
INSERT INTO scott.emp)需确保定义者有INSERT ON scott.emp或INSERT ANY TABLE,不能只靠角色
调用别人包时提示 PLS-00201 或 ORA-06550
即使已执行 GRANT EXECUTE ON b.pkg TO a,如果包体内部访问了其他用户对象(比如 SELECT 了 c.table1),而定义者 b 并没有对 c.table1 的 SELECT 权限,调用时仍会失败。
- 错误不是出在调用语句本身,而是包体中某条 SQL 执行时触发权限校验
- 必须让包属主
b显式获得所有被引用对象的权限(GRANT SELECT ON c.table1 TO b) - 若改用
AUTHID CURRENT_USER,则调用者a必须有对应权限,且其角色已激活(SESSION_ROLES非空)
Navicat 或 JDBC 创建索引/视图时报 ORA-01031
这类图形化工具或应用连接执行 DDL 时,权限校验更严格,常卡在三个地方:
- 缺系统权限:
CREATE INDEX或CREATE VIEW必须直接授予,RESOURCE角色不含这些权限 - 缺表空间配额:执行
CREATE INDEX ... TABLESPACE users前,需确认用户在USERS表空间有配额(SELECT * FROM DBA_TS_QUOTAS WHERE USERNAME = 'YOUR_USER') - 跨 schema 对象权限不足:建视图引用
other_user.table,除了CREATE VIEW,还必须有SELECT ON other_user.table,且不能仅靠角色授予
最易被忽略的是:应用连接(如 Python cx_Oracle、Java JDBC)默认不启用角色,而你在 SQL*Plus 里测试时可能手动 SET ROLE 过——生产环境连上来就是裸权限状态,得靠 ALTER USER ... DEFAULT ROLE ALL 或连接字符串里加 currentSchema 参数兜底。











