必须用 ROLE_SYS_PRIVS 查预定义角色权限,因 DBA_SYS_PRIVS 不记录内建角色(如 CONNECT)的固化权限;ROLE_SYS_PRIVS 需授权 SELECT_CATALOG_ROLE 并 SET ROLE 激活,且角色名严格区分大小写和引号。

必须用 ROLE_SYS_PRIVS,不是 DBA_SYS_PRIVS —— 后者查不到内建角色(如 CONNECT、RESOURCE)的默认权限。
为什么 DBA_SYS_PRIVS 查不到 CONNECT 的 CREATE SESSION?
因为 CONNECT 这类预定义角色的权限是固化在数据字典里的,不走 GRANT 流程,所以不会出现在 DBA_SYS_PRIVS 中。执行 SELECT * FROM DBA_SYS_PRIVS WHERE GRANTEE = 'CONNECT' 返回空,并不代表它没权限,只是这个视图只记录“谁被显式授予了什么”。
真正定义角色自身权限的,只有 ROLE_SYS_PRIVS:
SELECT privilege, admin_option FROM role_sys_privs WHERE role = 'CONNECT';
注意:Oracle 默认把角色名存为大写,WHERE role = 'connect' 查不到,得写 'CONNECT';如果建角色时用了双引号(如 "my_role"),查询时也必须带双引号。
ROLE_SYS_PRIVS 查询前要确认三件事
否则结果为空 ≠ 没权限,而是查不到:
- 当前用户是否有访问权限:普通用户默认无权查
ROLE_SYS_PRIVS,需先被授予SELECT_CATALOG_ROLE,且必须显式执行SET ROLE SELECT_CATALOG_ROLE激活(登录时自动启用的角色不生效) - 角色名大小写和引号严格匹配:
'CONNECT'✅,'connect'❌,"My_Role"必须写成"My_Role" - 刚执行
GRANT就查,可能因事务未提交而看不到:DDL 在 PL/SQL 块中不会自动提交,记得加COMMIT
嵌套角色权限不会自动展开,得递归查
ROLE_SYS_PRIVS 只返回目标角色“直接定义”的系统权限,不解析它所包含的其他角色。例如:APP_ADMIN 被授予了 SELECT_CATALOG_ROLE,后者自带 SELECT ANY DICTIONARY,但 SELECT * FROM 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',再对每个granted_role重复查一次role_sys_privs
Oracle 没有内置视图能自动展开多层嵌套,必须手动拼接或写递归查询(比如用 CONNECT BY 或 CTE)。
只想确认“激活后我实际能做什么”,用 SESSION_PRIVS 更轻量
如果你不关心权限来源路径,只关心当前会话生效的系统权限,SESSION_PRIVS 是最省事的选择:
SELECT * FROM session_privs;
它自动合并:当前用户直授权限 + 所有已激活角色的系统权限。无需额外权限,任何用户都可查。但注意:SESSION_PRIVS 只反映“当前已启用”的角色 —— 如果角色没被 SET ROLE 激活,就不会出现在结果里。
最容易被忽略的是:权限继承链里夹着带引号的角色名、刚授完权没提交、或者忘了 SET ROLE,这些都会让结果看起来“权限缺失”,其实只是查询条件或上下文没对上。


















