查角色具体权限必须用ROLE_SYS_PRIVS,因其唯一定义角色自身包含的系统权限;DBA_SYS_PRIVS仅记录显式授予的权限,不反映内建角色(如CONNECT)固化在数据字典中的默认权限,且需注意访问权限、大小写匹配、事务提交及嵌套角色需递归查询。
查角色具体权限,必须用 role_sys_privs,不是 dba_sys_privs —— 后者只记录“谁被显式授予了什么”,不反映角色自身的权限定义。
为什么直接查 DBA_SYS_PRIVS 会漏权限
内建角色(如 CONNECT、RESOURCE)的权限是固化在数据字典里的,不走 GRANT 流程,所以不会出现在 DBA_SYS_PRIVS 中。比如:
-
SELECT * FROM DBA_SYS_PRIVS WHERE GRANTEE = 'CONNECT'返回空,不代表它没权限 -
CONNECT默认含CREATE SESSION,但这条记录只存在于ROLE_SYS_PRIVS -
DBA_SYS_PRIVS里出现的记录,只说明“有人手动执行过GRANT ... TO CONNECT”,不是角色出厂配置
ROLE_SYS_PRIVS 查询前必须确认三件事
否则结果为空不是没权限,而是查不到:
- 当前用户是否有访问权限:普通用户默认看不到
ROLE_SYS_PRIVS,需先被授予SELECT_CATALOG_ROLE,且必须执行SET ROLE SELECT_CATALOG_ROLE激活,不能只靠登录时自动启用 - 角色名大小写和引号要严格匹配:Oracle 默认存为大写,
WHERE ROLE = 'connect'查不到,得写'CONNECT';如果建角色时用了双引号(如"my_role"),查询时也得带双引号 - 刚执行
GRANT就查,可能因事务未提交而看不到:DDL 在 PL/SQL 块中不会自动提交,记得加COMMIT
嵌套角色权限不会自动展开,得递归查
ROLE_SYS_PRIVS 只返回目标角色“直接定义”的系统权限,不解析它所包含的其他角色。例如:
-
APP_ADMIN被授予了SELECT_CATALOG_ROLE -
SELECT_CATALOG_ROLE自带SELECT ANY DICTIONARY - 但
SELECT * FROM ROLE_SYS_PRIVS WHERE ROLE = 'APP_ADMIN'不会显示SELECT ANY DICTIONARY
要补全,得两步走:
- 查它直接拥有的权限:
SELECT PRIVILEGE FROM ROLE_SYS_PRIVS WHERE ROLE = 'APP_ADMIN' - 查它包含的角色:
SELECT GRANTED_ROLE FROM ROLE_ROLE_PRIVS WHERE ROLE = 'APP_ADMIN' - 对每个
GRANTED_ROLE再查一次ROLE_SYS_PRIVS,手动拼接
更轻量的替代方案:用 SESSION_PRIVS 看当前会话生效权限
如果你只是想确认“这个角色激活后,我实际能做什么”,不用折腾权限树:
-
SELECT * FROM SESSION_PRIVS自动合并:当前用户直授权限 + 所有已激活角色的系统权限 - 无需额外权限,任何用户都可查
- 但注意:它只反映“当前已启用”的角色,得先确认
SELECT * FROM SESSION_ROLES里有没有目标角色
真正容易被忽略的是嵌套深度——生产环境审计时,只查一层 ROLE_SYS_PRIVS 会严重低估权限范围,必须逐层展开到最底层角色才可靠。


















