最准的是 SESSION_PRIVS,它实时反映当前会话所有生效系统权限,包括角色授予和 SET ROLE 后动态变化的权限;USER_SYS_PRIVS 仅显示直接授予且不随角色切换更新。

直接查 SESSION_PRIVS 最准,它反映的是此刻生效的全部系统权限,包括通过角色间接获得的、刚用 SET ROLE 切换后的权限。
为什么不能只看 USER_SYS_PRIVS
USER_SYS_PRIVS 只显示「直接授予当前用户」的系统权限,不包含角色带来的权限;而且它不会随 SET ROLE 动态更新。比如你被授予了 RESOURCE 角色,USER_SYS_PRIVS 里根本不会出现 CREATE TABLE —— 这个权限是角色给的,得靠 SESSION_PRIVS 或组合查询才能看到。
- 如果你刚执行
SET ROLE resource;,SESSION_PRIVS立刻多出十几条权限,USER_SYS_PRIVS一条都不会变 -
USER_SYS_PRIVS里带ADMIN_OPTION字段,能区分是否可转授;SESSION_PRIVS不带这个字段,因为它只关心“能不能用”,不关心“能不能给别人” - 开发或运维排查连不上、建不了表时,第一反应该查
SESSION_PRIVS,而不是翻USER_SYS_PRIVS确认自己有没有被“直授”
查角色来源:从 SESSION_ROLES 追到 ROLE_SYS_PRIVS
知道有权限还不够,有时得搞清「谁给的」——比如审计、权限回收、或发现不该有的权限。这时要两步走:
- 先查当前激活了哪些角色:
SELECT * FROM SESSION_ROLES;(注意不是USER_ROLE_PRIVS,后者只说“被授过”,但未必激活) - 再对每个角色查它带的权限:
SELECT PRIVILEGE FROM ROLE_SYS_PRIVS WHERE ROLE = 'RESOURCE';(角色名必须大写) - 典型组合如
CONNECT+RESOURCE,实际展开后共约 15 项系统权限,CREATE SESSION和CREATE TABLE就在这俩里面
DBA视角:查别人权限得用 DBA_SYS_PRIVS 和 DBA_ROLE_PRIVS
如果你有 DBA 权限,想查其他用户(比如 TOM)的系统权限,不能只靠 USER_* 视图 —— 它们只返回当前登录用户的数据。
- 查直授权限:
SELECT * FROM DBA_SYS_PRIVS WHERE GRANTEE = 'TOM';(用户名必须大写) - 查授予了哪些角色:
SELECT * FROM DBA_ROLE_PRIVS WHERE GRANTEE = 'TOM'; - 注意:
DBA_SYS_PRIVS不展开角色权限,所以即使TOM有RESOURCE角色,这里也看不到CREATE TABLE;得配合DBA_ROLE_PRIVS+ROLE_SYS_PRIVS手动拼接
真正容易被忽略的是:权限生效依赖「角色是否激活」。哪怕 USER_ROLE_PRIVS 显示你有 DBA 角色,如果没执行 SET ROLE DBA;,SESSION_PRIVS 里就不会出现 ALTER DATABASE 这类高危权限 —— 很多越权操作失败,根源就在这里。


















