DBA_SYS_PRIVS仅显示用户被显式授予的系统权限,不包含角色继承权限;需结合DBA_ROLE_PRIVS等视图递归查询角色链才能完整获取权限路径。
直接查 dba_sys_privs 就能拿到用户被显式授予的系统权限,但要注意它不包含角色继承来的权限,也不反映当前是否实际生效。
查指定用户的直接系统权限(DBA_SYS_PRIVS 基础用法)
这个视图只记录通过 GRANT ... TO user 直接授给用户的系统权限,比如 CREATE TABLE、DROP ANY INDEX。它不展示通过角色间接获得的权限。
执行以下语句即可:
SELECT grantee, privilege, admin_option FROM dba_sys_privs WHERE grantee = 'SCOTT';
-
grantee是用户名(注意大小写,通常为大写) -
privilege是具体权限名,如UNLIMITED TABLESPACE -
admin_option为YES表示该用户还能把此权限再授给别人
为什么查不到某些“明明有”的权限?
常见原因是权限来自角色——比如 SCOTT 被授予了 CONNECT 角色,而 CONNECT 包含 CREATE SESSION,但 DBA_SYS_PRIVS 不会列出这条记录。
要补全这部分,得连查角色授权链:
SELECT p.privilege FROM dba_role_privs r, dba_sys_privs p WHERE r.grantee = 'SCOTT' AND r.granted_role = p.grantee;
- 先从
DBA_ROLE_PRIVS找出用户拥有的角色 - 再用这些角色名去
DBA_SYS_PRIVS查它们各自持有的系统权限 - 注意:嵌套角色(角色 A 授予角色 B)默认不递归展开,需手动多层 JOIN 或用递归查询
DBA_SYS_PRIVS 的权限范围与性能影响
该视图需要 SELECT_CATALOG_ROLE 或 DBA 权限才能访问,普通用户查不到其他用户的记录。在高并发环境频繁查询它本身开销不大,但若搭配子查询或跨多视图关联(比如联合 DBA_ROLE_PRIVS + ROLE_ROLE_PRIVS),容易触发大量字典表扫描。
- 生产环境建议加索引提示(如
/*+ INDEX(dba_sys_privs i_dbasypri1) */)或限制grantee为具体值,避免全表扫 - 如果只要判断某权限是否存在,用
EXISTS比SELECT *更轻量 - Oracle 12c 及以后版本中,
DBA_SYS_PRIVS底层依赖sys.sysauth$,字段privilege存的是数字编码,视图做了翻译,所以无需额外解码
真正难的是厘清“权限生效路径”:直接授予、角色授予、公共角色、甚至细粒度访问控制(FGAC)策略都可能参与其中。DBA_SYS_PRIVS 只是拼图的第一块,漏掉角色链就等于只看了半张权限地图。


















