ora-01031错误本质是权限已授但未生效,应先查session_privs和session_roles确认当前会话实际激活的权限与角色,而非直接授dba;pl/sql中角色权限默认不可用,需显式授权或改用authid current_user。

先查 SESSION_PRIVS 和 SESSION_ROLES,别急着 GRANT
ORA-01031 报错时,最常被忽略的是“权限已授但未生效”。直接 GRANT DBA TO user 不仅高危,还可能无效。真正该看的是当前会话运行时的权限快照:SELECT * FROM SESSION_PRIVS 显示当前可用的系统权限(不含角色间接授予的),SELECT * FROM SESSION_ROLES 显示当前已启用的角色。如果 CREATE TABLE 不在 SESSION_PRIVS 结果里,说明这个权限压根没激活——哪怕 DBA_ROLE_PRIVS 显示你有 DBA 角色。
PL/SQL 里 EXECUTE IMMEDIATE 失败,大概率是角色权限失效
存储过程或函数中用 EXECUTE IMMEDIATE 执行 DDL(如 CREATE TABLE)报 ORA-01031,几乎可以确定是定义者权限(DEFINER’S RIGHTS)下角色权限被忽略。Oracle 默认不把通过角色获得的权限暴露给 PL/SQL 运行时上下文。解决方案只有两个:
- 显式授权:DBA 执行
GRANT CREATE TABLE TO your_user(不走角色) - 改用调用者权限:把过程头改成
AUTHID CURRENT_USER,但前提是调用者已手动执行过SET ROLE ALL或对应角色
注意:CREATE ANY TABLE 属于高危 system privilege,生产环境应避免直接授予应用用户。
JDBC / cx_Oracle 连接后角色默认不启用
Java 或 Python 应用连 Oracle,即使数据库里已 GRANT DBA TO app_user,只要没在连接后显式执行 SET ROLE ALL,SESSION_ROLES 就为空。某些旧版 JDBC 驱动(如 ojdbc6)甚至不支持自动执行 SET ROLE,必须在代码里手动提交。示例(Python + cx_Oracle):
conn = cx_Oracle.connect("app_user/pass@db")
cursor = conn.cursor()
cursor.execute("SET ROLE ALL") # 必须显式执行
cursor.execute("CREATE TABLE t1(id NUMBER)")
若 DBA 角色设了密码,语句得写成 SET ROLE DBA IDENTIFIED BY "xxx";没密码则不能带 IDENTIFIED BY,否则报错。
OS 认证用户(sqlplus / as sysdba)失败,先看组和密码文件
用操作系统账号本地登录报 ORA-01031,问题通常不在数据库配置,而在 OS 层:
- Linux 下,当前用户必须属于
dba组(不是oinstall);Windows 下需在ORA_DBA组中 -
SQLNET.AUTHENTICATION_SERVICES在 Linux 可不设或设为(ALL),Windows 必须是(NTS) - 检查密码文件:
SELECT * FROM V$PWFILE_USERS必须返回SYS行;文件路径通常是$ORACLE_HOME/dbs/orapw$ORACLE_SID,权限应为640或6751
真正卡住人的地方,往往不是“没授权”,而是“授权了但没激活”、或者“激活了但在 PL/SQL 里不可见”。每次遇到 ORA-01031,第一反应不该是加权限,而是立刻查那两个视图——它们才是唯一可信的运行时证据。











