查当前会话已启用的角色用session_roles,它只反映此刻实际生效的角色;查用户直接受授角色用user_role_privs或dba_role_privs;查角色嵌套继承需递归查询role_role_privs;验证权限来源需联合dba_role_privs与role_tab_privs/role_sys_privs。

查当前会话已启用的角色用 SESSION_ROLES
这是最快速的起点,但只告诉你“此刻能用哪些角色”,不告诉你“谁给的、怎么来的”。执行:SELECT * FROM SESSION_ROLES;
结果为空 ≠ 没角色,可能是:
• 没执行过 SET ROLE
• 用户的 DEFAULT ROLE 被显式禁用(如 ALTER USER ... DEFAULT ROLE NONE)
• 角色虽被授予,但未激活——它存在,只是没生效
查用户直接受授的角色用 USER_ROLE_PRIVS 或 DBA_ROLE_PRIVS
普通用户查自己被谁直接授了哪些角色,用 USER_ROLE_PRIVS 就够了:SELECT GRANTED_ROLE, ADMIN_OPTION, DEFAULT_ROLE FROM USER_ROLE_PRIVS;
有 DBA 权限时,可用 DBA_ROLE_PRIVS 查任意用户,但注意:
• GRANTEE 是用户名(大写),不是角色名
• ADMIN_OPTION = 'YES' 表示你能把这个角色再授给别人
• DEFAULT_ROLE = 'YES' 表示登录后自动启用(除非被 ALTER USER ... DEFAULT ROLE NONE 覆盖)
查角色嵌套继承链必须递归查 ROLE_ROLE_PRIVS
一个角色 A 授予了角色 B,B 又授予了你,那 A 的权限就间接属于你——但 USER_ROLE_PRIVS 不体现这层关系。要挖出完整链条,得靠:SELECT LEVEL, GRANTED_ROLE, GRANTEE FROM ROLE_ROLE_PRIVS START WITH GRANTEE IN (SELECT GRANTED_ROLE FROM USER_ROLE_PRIVS) CONNECT BY PRIOR GRANTED_ROLE = GRANTEE;
关键点:
• GRANTEE 是“接收方”,GRANTED_ROLE 是“被授予的角色”——方向别反
• 如果出现 ORA-01436: CONNECT BY loop,说明存在自循环(比如角色 A 授予了自己),得先清理
• 结果是树状展开,但实际继承关系可能是有向图(多个上级授予同一角色),单次查询只能从一个入口开始
验证某个权限是否来自角色,得联合查 DBA_ROLE_PRIVS + ROLE_TAB_PRIVS 或 ROLE_SYS_PRIVS
比如用户 ALICE 能查 EMP 表,但 DBA_TAB_PRIVS 里 GRANTEE 字段显示的是 'HR_ROLE',不是 'ALICE'——这就提示权限来自角色。确认路径分两步:
• 先查 ALICE 被授了哪些角色:SELECT GRANTED_ROLE FROM DBA_ROLE_PRIVS WHERE GRANTEE = 'ALICE'
• 再查这些角色是否有对应权限:SELECT ROLE, TABLE_NAME, PRIVILEGE FROM ROLE_TAB_PRIVS WHERE ROLE IN ('HR_ROLE', ...)
注意:
• ROLE_TAB_PRIVS 和 ROLE_SYS_PRIVS 都不递归展开嵌套角色,只返回该角色“直接定义”的权限
• 内建角色如 CONNECT 的 CREATE SESSION 不在 DBA_SYS_PRIVS 里,必须查 ROLE_SYS_PRIVS,且需提前 SET ROLE SELECT_CATALOG_ROLE 并注意大小写
角色继承不是单线链条,而是可能分叉、重叠、带选项控制的依赖图;人工看几层还行,超过三层建议导出文本后用缩进或工具辅助梳理层级。真正难的不是查到数据,而是判断哪条路径在当前会话生效、哪个 ADMIN_OPTION 允许你继续授权、以及隐式权限(如连接本身)根本不会出现在任何权限视图里。











