查角色直接包含的系统权限应使用ROLE_SYS_PRIVS视图,它仅返回角色与系统权限的直连关系,不递归展开子角色,结果准确可靠;查询时角色名须大写,权限名大小写不敏感。

查角色直接包含的系统权限用 ROLE_SYS_PRIVS
想看某个角色(比如 RESOURCE 或 DBA)里明明白白写了哪些系统权限,就查 ROLE_SYS_PRIVS。它只存「角色 → 系统权限」这一层直连关系,不递归、不展开子角色,结果干净可预期。
-
SELECT privilege FROM ROLE_SYS_PRIVS WHERE role = 'RESOURCE';—— 注意角色名必须大写,'resource'查不到 - 权限名大小写不敏感:
'CREATE TABLE'和'create table'效果一样 - 如果查不到结果,先确认角色是否存在:
SELECT * FROM DBA_ROLES WHERE ROLE = 'YOUR_ROLE'; - 该视图对所有用户可见,不需要 DBA 权限
为什么不用 DBA_SYS_PRIVS 查角色的权限?
DBA_SYS_PRIVS 的 GRANTEE 字段虽然可以填角色名,但 Oracle 在这里不会按你理解的方式过滤——它默认只返回当前 session 有效角色的权限快照,且行为受权限上下文影响极大。实际执行时经常返回空或漏数据,属于典型误用。
- 错误写法:
SELECT privilege FROM DBA_SYS_PRIVS WHERE grantee = 'RESOURCE'; - 即使语句不报错,结果也极不可靠:可能为空、可能只含部分权限、可能混入用户直授权限
- 真正该用
DBA_SYS_PRIVS的场景是查「某用户被直接授予了哪些系统权限」,不是查角色
要查嵌套角色链里的全部系统权限怎么办?
ROLE_SYS_PRIVS 不递归,所以如果 APP_ADMIN 角色又包含了 SELECT_CATALOG_ROLE,后者的权限不会自动出现在查询结果里。Oracle 没有内置递归视图或函数帮你一键展开,必须手动拼接。
- 先查角色 A 包含哪些子角色:
SELECT granted_role FROM ROLE_ROLE_PRIVS WHERE role = 'APP_ADMIN'; - 再对每个子角色查其系统权限:
SELECT privilege FROM ROLE_SYS_PRIVS WHERE role = 'SELECT_CATALOG_ROLE'; - 需要多层嵌套时,得用
UNION ALL手动合并,或者写 PL/SQL 循环处理 - 注意:
ROLE_ROLE_PRIVS本身也不递归,它只记录直接授予关系
常见错误现象和容易忽略的点
很多人在查权限时卡在“明明给了角色,却查不到对应权限”,问题往往出在边界认知上。
- 把对象权限(如
SELECT、UPDATE)和系统权限混为一谈:ROLE_SYS_PRIVS完全不包含对象权限;对象权限必须绑定具体对象,查ROLE_TAB_PRIVS - 误以为
CREATE SESSION会出现在权限视图里——它不会,只要能连上库,这个权限就在,但不在任何*_SYS_PRIVS视图中 - 查
USER_SYS_PRIVS时发现权限没更新:那是正常的,它反映的是授权快照,不是实时会话状态;刚SET ROLE后不会立刻体现 - 用小写角色名查询失败却不检查大小写——Oracle 数据字典里角色名默认大写存储


















