应先查 session_privs 确认 create table 权限是否实际生效;若缺失,说明权限未激活或仅通过角色授予(pl/sql 中无效),需直授权限或启用角色(如 set role all),并确保配套权限(create session、表空间配额)齐备。
查 session_privs 确认 create table 是否真可用
ora-01031 报错时,别急着 grant dba;先在出错会话里执行 select * from session_privs;。如果结果里没有 create table,说明这个权限压根没生效——哪怕 dba_role_privs 显示你已被授予 dba 角色。常见陷阱是:dba 角色默认不启用,或连接方式(如 jdbc)根本不会自动激活任何角色。
跨 schema 建表或用 EXECUTE IMMEDIATE 时权限必须直授
存储过程里写 EXECUTE IMMEDIATE 'CREATE TABLE t1(id NUMBER)' 报 ORA-01031,大概率不是缺 CREATE TABLE,而是该权限是通过角色给的。Oracle 在 DEFINER’S RIGHTS 模式下会忽略角色权限。
- 方案一(推荐):DBA 执行
GRANT CREATE TABLE TO your_user;,不走角色 - 方案二:改用调用者权限,把过程头改成
AUTHID CURRENT_USER,但前提是调用者自己已启用对应角色 - 别漏掉配套权限:
CREATE SESSION和UNLIMITED TABLESPACE或具体表空间配额也得有,否则建表仍失败
JDBC/cx_Oracle 连接后必须手动 SET ROLE
Java 或 Python 应用连 Oracle,默认不会启用任何角色,SESSION_ROLES 是空的。光靠 GRANT DBA TO app_user 没用。
- 连接成功后立刻执行
SET ROLE ALL;(如果角色无密码) - 如果有密码,得写
SET ROLE role_name IDENTIFIED BY 'pwd'; - 某些驱动(如 older ojdbc)不支持 SET ROLE 自动执行,得在应用代码里显式提交这条语句
OS 认证用户(IDENTIFIED EXTERNALLY)容易被忽略的权限激活
用操作系统账号直接登录(比如 sqlplus /),CREATE TABLE 仍报 ORA-01031?问题常出在关键系统权限没激活。
-
SELECT * FROM SESSION_ROLES;很可能为空,即使 DBA 角色已授 - 必须手动执行
SET ROLE ALL;或SET ROLE DBA; - 如果 DBA 角色设了密码,不带
IDENTIFIED BY就会失败 - 密码文件权限不对(比如缺少 setuid 位)也会导致 OS 认证用户拿不到预期权限,需检查
$ORACLE_HOME/dbs/orapw$ORACLE_SID的权限是否为 640 或 6751
真正卡住人的地方往往不是“没授权”,而是“授权了但没激活”或者“激活了但在 PL/SQL 里不可见”。每次遇到 ORA-01031,第一反应不该是加权限,而是先看 SESSION_PRIVS 和 SESSION_ROLES —— 这两个视图才是当前会话的真实权限快照。











