查角色系统权限必须用ROLE_SYS_PRIVS,它唯一定义角色本身包含的系统权限;DBA_SYS_PRIVS仅记录显式授予的权限,不反映内建角色的固化权限,且ROLE_SYS_PRIVS需权限+激活才能访问。
查角色系统权限必须用ROLE_SYS_PRIVS,不是DBA_SYS_PRIVS
role_sys_privs 是唯一正确定义「角色本身包含哪些系统权限」的视图。dba_sys_privs 只记录「谁被直接授予了某系统权限」,包括用户或角色——但它不表示该角色在逻辑上「拥有」这些权限,只是说这个角色被显式 grant 过。比如执行 grant create session to connect,这条记录会进 dba_sys_privs;但真正体现 connect 角色出厂默认权限的,是 role_sys_privs 里预置的那几条。
常见错误包括:
- 在
DBA_SYS_PRIVS中查WHERE GRANTEE = 'CONNECT',发现为空就以为没权限——其实 CONNECT 是 Oracle 内建角色,其权限由数据字典固化,不走 GRANT 流程,所以不会出现在 DBA_SYS_PRIVS - 误以为
ROLE_ROLE_PRIVS能查系统权限——它只告诉你「角色 A 包含角色 B」,不涉及任何系统级操作能力
查询前必须确认当前用户有访问权限
ROLE_SYS_PRIVS 对普通用户不可见,即使你刚用 GRANT SELECT_CATALOG_ROLE TO your_user 授了权,也得重新登录或执行 SET ROLE SELECT_CATALOG_ROLE 才能查。否则直接 SELECT * FROM ROLE_SYS_PRIVS 会返回空结果,不是没数据,而是没权限读。
替代方案(无需额外权限):
- 查当前会话已激活角色的系统权限:
SELECT * FROM SESSION_PRIVS——它自动合并了用户直授权限 + 所有已启用角色的系统权限 - 查当前用户被授了哪些角色:
SELECT * FROM USER_ROLE_PRIVS,再结合SESSION_ROLES确认哪些已激活
大小写、引号、事务提交都影响查询结果
Oracle 默认把角色名存为大写,所以 WHERE ROLE = 'connect' 查不到,必须写 'CONNECT'。如果建角色时用了双引号,比如 CREATE ROLE "my_role",那查询时就得严格匹配 WHERE ROLE = 'my_role' 并带双引号。
另一个容易卡住的点:刚执行完 GRANT CREATE TABLE TO my_role 就去查 ROLE_SYS_PRIVS,结果为空。这不是视图延迟,而是你还在一个未提交的事务里——GRANT 是 DDL,在多数客户端中会隐式提交,但在 PL/SQL 块中不会,记得手动加 COMMIT。
嵌套角色权限不会自动展开,必须递归查
ROLE_SYS_PRIVS 只返回目标角色「直接定义」的系统权限,不递归解析它所包含的其他角色。例如角色 APP_ADMIN 被授予了 SELECT_CATALOG_ROLE,而后者自带 SELECT ANY DICTIONARY,但你在 ROLE_SYS_PRIVS WHERE ROLE = 'APP_ADMIN' 里看不到这条。
要拿到完整权限集,得手动两步走:
- 先查直接权限:
SELECT PRIVILEGE FROM ROLE_SYS_PRIVS WHERE ROLE = 'APP_ADMIN' - 再查它包含的角色:
SELECT GRANTED_ROLE FROM ROLE_ROLE_PRIVS WHERE ROLE = 'APP_ADMIN',对每个结果重复第一步
生产环境做权限审计时,漏掉这一步等于默认信任角色不嵌套——现实中 DBA、AQ_ADMINISTRATOR_ROLE、EXP_FULL_DATABASE 都是典型多层嵌套角色。


















