查用户全部系统权限需联合DBA_SYS_PRIVS与ROLE_SYS_PRIVS去重,因DBA_SYS_PRIVS仅含直接授权,不包含角色继承权限;HR必须大写;自定义嵌套角色需递归查询;普通用户可用USER_*视图替代。

直接查 DBA_SYS_PRIVS 只能看到“直接授予”的系统权限,漏掉角色继承来的权限——这是最常踩的坑。要真正看清一个用户“实际能用哪些系统权限”,必须把直接授权 + 所有已授角色携带的权限合并去重。
查指定用户全部系统权限(含角色继承)
用 DBA_SYS_PRIVS 和 ROLE_SYS_PRIVS 联合查询,关键在于递归展开用户拥有的所有角色(包括嵌套角色需额外处理,但 Oracle 11g+ 默认不支持角色嵌套继承系统权限,所以两层足够):
SELECT DISTINCT privilege FROM ( -- 直接授予该用户的系统权限 SELECT privilege FROM dba_sys_privs WHERE grantee = 'HR' UNION ALL -- 该用户被授予的角色所带的系统权限 SELECT rp.privilege FROM dba_role_privs drp JOIN role_sys_privs rp ON drp.granted_role = rp.role WHERE drp.grantee = 'HR' ) ORDER BY privilege;
-
HR必须大写,Oracle 默认用户名/角色名是大写的,小写会查不到 - 如果用户有自定义角色,且该角色又授予了其他角色(即角色嵌套),上面 SQL 不覆盖;此时需用递归 CTE 或 PL/SQL,但生产环境极少需要
- 普通用户无法访问
DBA_*视图,只能查自己:用USER_SYS_PRIVS+USER_ROLE_PRIVS+ROLE_SYS_PRIVS组合(无需 DBA 权限)
为什么不能只用 DBA_SYS_PRIVS?
因为 DBA_SYS_PRIVS 只存“直接授予”关系。比如用户 HR 被授予了 RESOURCE 角色,而 RESOURCE 自带 CREATE TABLE、CREATE SEQUENCE 等权限——这些不会出现在 DBA_SYS_PRIVS 中 grantee = 'HR' 的记录里。
- 典型错误现象:
SELECT * FROM DBA_SYS_PRIVS WHERE GRANTEE = 'HR';返回空或只有UNLIMITED TABLESPACE,但HR明明能建表 -
RESOURCE角色本身不带CREATE SESSION,所以哪怕用户有RESOURCE,也必须单独授予CONNECT或显式给CREATE SESSION,否则连不上库 -
UNLIMITED TABLESPACE是个特例:它不能通过角色授予,只能直接授给用户,所以一定出现在DBA_SYS_PRIVS里
快速验证用户能否执行某操作(如建表)
与其罗列全部权限,不如直接测行为。以下 SQL 可判断用户是否具备建表能力:
SELECT COUNT(*)
FROM dba_role_privs
WHERE grantee = 'HR' AND granted_role IN ('RESOURCE', 'DBA')
UNION ALL
SELECT COUNT(*)
FROM dba_sys_privs
WHERE grantee = 'HR' AND privilege = 'CREATE TABLE';- 返回结果中任意一行 > 0,就说明能建表
- 注意:
DBA角色隐含所有系统权限,只要用户有DBA角色,无需再查其他 - 如果应用部署账号只需最小权限,务必避开
DBA和UNLIMITED TABLESPACE——后者容易导致表空间失控
真正难搞的不是查权限,而是厘清“谁在什么时候通过什么路径授了什么”。尤其是跨多个角色、中间有自定义角色、还混用 ADMIN OPTION 时,DBA_ROLE_PRIVS 的 admin_option 字段决定该用户能否继续转授角色——这点经常被忽略,却直接影响权限扩散风险。


















