查用户直接系统权限用DBA_SYS_PRIVS(需DBA权限),角色权限用DBA_ROLE_PRIVS,角色所含系统权限用ROLE_SYS_PRIVS(仅当前会话角色)或DBA_SYS_PRIVS WHERE GRANTEE='角色名',完整继承链需手动递归查询。
查用户直接拥有的系统权限用 DBA_SYS_PRIVS
这是最基础的起点:只看该用户被显式授予的系统权限,不包含通过角色继承来的。比如执行 select privilege from dba_sys_privs where grantee = 'scott',返回的就是直接给 scott 的权限,像 create session 或 unlimited tablespace。
注意:DBA_SYS_PRIVS 需要 DBA 权限才能查;普通用户只能查 USER_SYS_PRIVS(仅自身)或 SESSION_PRIVS(当前会话生效的权限,含已激活角色带来的)。
-
ADMIN_OPTION为 YES 表示该用户还能把这权限再授给别人 - 大小写敏感:Oracle 默认用户名、角色名全大写,
WHERE GRANTEE = 'scott'查不到结果 - 如果查不到记录,不代表没权限——可能全靠角色继承
查用户被授予了哪些角色用 DBA_ROLE_PRIVS
角色是权限聚合的关键中间层。用户本身权限常来自角色(如 CONNECT、RESOURCE、DBA),而角色又可被授予其他角色,形成嵌套。
执行 SELECT GRANTED_ROLE, ADMIN_OPTION, DEFAULT_ROLE FROM DBA_ROLE_PRIVS WHERE GRANTEE = 'SCOTT',能列出 SCOTT 拥有的所有角色。其中:
-
DEFAULT_ROLE为 YES 表示登录时自动激活(否则需SET ROLE手动启用) -
ADMIN_OPTION为 YES 表示 SCOTT 可以把这个角色再授予别人 - 角色名本身也是大写的,
'connect'和'CONNECT'效果不同
查某个角色包含哪些系统权限用 ROLE_SYS_PRIVS
这个视图只反映“当前会话用户所拥有的角色”对应的系统权限,不能跨用户查。比如你用 SCOTT 登录后执行 SELECT * FROM ROLE_SYS_PRIVS WHERE ROLE = 'CONNECT',能看到 CONNECT 角色默认带的 CREATE SESSION 等权限。
但如果你想查别人(比如 HR)的 CONNECT 角色内容,ROLE_SYS_PRIVS 就不适用——它不认 GRANTEE 字段,只按当前 session 角色过滤。
- 真正跨用户查角色定义,得用
DBA_SYS_PRIVS WHERE GRANTEE = 'CONNECT' -
ROLE_SYS_PRIVS不显示对象权限,只管系统级权限(如CREATE TABLE) - 嵌套角色(A 角色含 B,B 含 C)不会在
ROLE_SYS_PRIVS中展开,需递归查DBA_ROLE_PRIVS
递归查权限继承链必须手动拼 UNION ALL + 子查询
Oracle 没有内置函数或视图直接输出“用户 X 的全部有效系统权限(含角色层层继承)”。必须自己构造递归逻辑,典型写法是:
SELECT PRIVILEGE FROM DBA_SYS_PRIVS WHERE GRANTEE = 'SCOTT'
UNION
SELECT PRIVILEGE FROM DBA_SYS_PRIVS WHERE GRANTEE IN (
SELECT GRANTED_ROLE FROM DBA_ROLE_PRIVS WHERE GRANTEE = 'SCOTT'
)
UNION
SELECT PRIVILEGE FROM DBA_SYS_PRIVS WHERE GRANTEE IN (
SELECT GRANTED_ROLE FROM DBA_ROLE_PRIVS WHERE GRANTEE IN (
SELECT GRANTED_ROLE FROM DBA_ROLE_PRIVS WHERE GRANTEE = 'SCOTT'
)
);
这个三层结构覆盖常见嵌套(用户 → 角色 → 角色 → 权限),但实际中角色深度可能更深,且无法自动终止。更稳妥的做法是写 PL/SQL 过程遍历,或导出后用脚本处理。
容易忽略的一点:DBA_TAB_PRIVS 中的对象权限(如对某张表的 SELECT)也遵循同样继承规则,但它和系统权限分开存储,不能混在上面的 UNION 里查——得另起一套针对 TABLE_NAME + PRIVILEGE + GRANTEE 的递归逻辑。











