查当前会话实际生效的权限,必须执行select from session_roles和select from session_privs确认启用角色与可用系统权限,而非仅看dba_role_privs等授予权限视图;jdbc或os认证连接需显式set role,跨schema操作及pl/sql中权限须直授。
查当前会话实际生效的权限,别只看“授过什么”
ora-01031 报错时,dba_role_privs 或 dba_sys_privs 里显示“已授予权限”,不代表当前会话能用。真正管用的是运行时上下文里的权限。
必须在出错会话中立刻执行:
SELECT * FROM SESSION_ROLES;
如果期望的角色(比如 SELECT_CATALOG_ROLE)没出现在结果里,说明它没启用;再执行:
SELECT * FROM SESSION_PRIVS;
这里列出的是当前会话**实际可用的系统权限**。如果报 CREATE VIEW 错,但 SESSION_PRIVS 里没有 CREATE VIEW,那就确认缺这个;如果只有 CREATE ANY VIEW,说明你被赋予的是越权能力,而非基础权限。
- 用 JDBC / cx_Oracle 连接时,默认不启用任何角色,需连接后显式执行
SET ROLE ALL或SET ROLE role_name - OS 认证用户(
IDENTIFIED EXTERNALLY)往往不会自动激活关键系统权限,也得手动SET ROLE - 角色有密码?执行
SET ROLE role_name IDENTIFIED BY password
跨 schema 创建视图时,对象权限必须直授,不能靠角色
执行 CREATE OR REPLACE VIEW v_a AS SELECT * FROM other_schema.t 失败,光有 CREATE VIEW 系统权限没用。你还得确保当前用户对 other_schema.t 有 SELECT 权限——而且必须是对象属主(比如 other_schema 用户)直接授予的,不能仅靠角色。
- 角色里的
SELECT权限在跨 schema 引用时无效,尤其在 PL/SQL 中完全不可见 - 对象属主执行:
GRANT SELECT ON t TO your_user;,不是GRANT SELECT_CATALOG_ROLE TO your_user; - 如果视图里查了
DBA_TABLES这类数据字典,还需SELECT ANY DICTIONARY或启用SELECT_CATALOG_ROLE
存储过程里建表/建视图,权限必须直授或改用 AUTHID CURRENT_USER
PL/SQL 块默认使用 DEFINER’S RIGHTS,这时通过角色获得的权限全部失效。哪怕你有 DBA 角色,EXECUTE IMMEDIATE 'CREATE TABLE t1(id NUMBER)' 仍会报 ORA-01031。
- 方案一(推荐):让 DBA 直接授予权限给用户:
GRANT CREATE TABLE TO your_user;,不走角色 - 方案二:改用调用者权限:
CREATE OR REPLACE PROCEDURE p AUTHID CURRENT_USER AS BEGIN ... END;,此时依赖调用者当前会话的实际权限(包括已启用的角色) -
GRANT DBA TO user后仍失败?大概率是角色没启用,或该角色未带WITH ADMIN OPTION(无法转授)
sqlplus / as sysdba 失败?先查操作系统组权限
本地用 OS 认证连 SYSDBA 报 ORA-01031,95% 是操作系统层面问题,和数据库账号、密码、角色完全无关。
- Linux:确认
oracle用户属于dba组:id oracle输出必须含groups=...dba;grep ^dba /etc/group必须包含oracle - Windows:当前登录用户必须在本地
ORA_DBA组,并且%ORACLE_HOME%\network\admin\sqlnet.ora中有且仅有:SQLNET.AUTHENTICATION_SERVICES = (NTS) - 容器或 systemd 环境下,
sudo su - oracle可能不继承组信息,应改用su - oracle
最常被忽略的点:改完组成员后没重新登录 shell,或 Windows 域账户离线导致 NTS 认证失败。











