ora-01979错误本质是密码校验失败,源于角色被创建为identified by类型但set role时未提供或错输密码;需查dba_roles中password_required字段确认,set role all except无法绕过校验,启用带密码角色会自动禁用其他默认角色。

ORA-01979错误本质是密码校验失败,不是权限或语法问题
这个错误明确告诉你:某个角色需要密码才能启用,但你没提供,或提供的不对。它和用户密码、登录凭证完全无关,只取决于角色是否被创建为 IDENTIFIED BY 类型。常见误判是去查用户权限或 GRANT 语句,其实只要确认角色定义方式就锁定了根因。
检查角色是否带密码:查 DBA_ROLES 和 ROLE_ROLE_PRIVS
先确认当前会话能启用哪些角色,以及它们的认证方式:
SELECT role, password_required FROM dba_roles WHERE role IN (SELECT granted_role FROM dba_role_privs WHERE grantee = USER);- 如果某角色的
PASSWORD_REQUIRED列值为YES,就必须在SET ROLE时带上IDENTIFIED BY - 注意:
DBA_ROLES需要 DBA 权限;普通用户可用USER_ROLE_PRIVS查自己被授的角色,但看不到PASSWORD_REQUIRED字段 —— 这时候得找 DBA 或换账号查
SET ROLE ALL 失败时,不能靠 EXCEPT 绕过密码角色
SET ROLE ALL EXCEPT role_name 看起来能跳过有问题的角色,但 Oracle 会提前校验所有已授予角色的密码要求 —— 只要其中任一角色设了密码,即使你用 EXCEPT 排除了它,这条语句仍会报 ORA-01979。
- 正确做法是显式列出所有无密码角色:
SET ROLE role1, role2, role3; - 或者逐个启用带密码的角色:
SET ROLE r2 IDENTIFIED BY 'oracle'; -
SET ROLE NONE总是安全的,可用于重置会话角色状态 - 升级到 12c+ 后更严格:如果角色密码是用
ALTER ROLE ... IDENTIFIED BY VALUES从旧版本迁移来的,很可能哈希不兼容,必须用明文重设密码
带密码角色启用后,其他默认角色会被自动禁用
Oracle 的角色激活是“覆盖式”的:SET ROLE r2 IDENTIFIED BY 'xxx' 执行后,之前通过 DEFAULT ROLE 自动启用的角色(比如 r1)会立刻失效,哪怕 r1 本身不带密码。
- 验证当前生效角色:运行
SELECT * FROM session_roles; - 若需保留多个角色权限,要么把它们都放进一条
SET ROLE语句(都满足密码要求),要么确保目标角色已包含所需权限(例如让r2GRANT了r1的权限) - 别依赖
DEFAULT ROLE在启用带密码角色后继续生效 —— 这是设计行为,不是 bug
实际调试时最容易卡在“以为 EXCEPT 能规避校验”和“没意识到启用新角色会清空旧角色”。密码本身是否正确,往往只差一个大小写或空格 —— 建议把密码存进变量再引用,避免手动输入出错。











