查表权限用DBA_TAB_PRIVS而非DBA_SYS_PRIVS,因其专存对象级权限(如对EMP表的SELECT),每行记录GRANTEE、GRANTOR、TABLE_NAME、PRIVILEGE;DBA_SYS_PRIVS仅存系统级权限(如CREATE TABLE)。
查表权限为什么用 DBA_TAB_PRIVS 而不是 DBA_SYS_PRIVS
因为 dba_sys_privs 存的是系统级权限(比如 create table、drop any table),而表对象上的具体授权(如对 emp 表的 select 权限)只记录在 dba_tab_privs 里。dba_tab_privs 的每一行代表「谁(grantee)被谁(grantor)授予了对哪个表(table_name)的哪种权限(privilege)」。
常见错误是直接查 DBA_SYS_PRIVS 找不到表级权限,或者漏掉 OWNER 字段导致查错 schema 下的同名表。
查某张表的所有权限分配(含 grant option 和层级)
执行以下语句时,必须指定 OWNER(即 schema 名),否则可能查到多个同名表的结果:
SELECT GRANTOR, GRANTEE, PRIVILEGE, GRANTABLE, HIERARCHY FROM DBA_TAB_PRIVS WHERE OWNER = 'SCOTT' AND TABLE_NAME = 'EMP';
GRANTABLE 为 YES 表示该权限可再转授;HIERARCHY 为 YES 表示该权限支持对象继承(仅适用于 SELECT 等少数权限,在启用细粒度访问控制时才有意义)。
- 如果只关心直接授权,忽略
HIERARCHY列即可 -
GRANTEE可能是用户、角色,甚至PUBLIC—— 查到PUBLIC要特别注意,意味着所有用户都能访问 - 权限大小写不敏感,但表名和 owner 默认大写,除非建表时加了双引号
查某个用户/角色在哪些表上有权限
用 GRANTEE 过滤更实用,尤其排查越权访问或权限收敛:
SELECT OWNER, TABLE_NAME, PRIVILEGE, GRANTABLE
FROM DBA_TAB_PRIVS
WHERE GRANTEE IN ('HR', 'APP_ROLE');
注意点:
- 角色权限不会自动展开,如果想看到该角色成员实际能访问哪些表,得结合
ROLE_ROLE_PRIVS和DBA_ROLE_PRIVS递归查,不能只靠这一张表 -
GRANTEE值区分大小写,但 Oracle 默认存储为大写;若曾用小写加引号创建用户(如"testuser"),需按原样匹配 - 某些权限(如
REFERENCES)容易被忽略,但它允许创建外键,属于隐式数据依赖风险点
权限查询结果为空?先确认三件事
查不到预期权限,大概率不是没授,而是条件没对上:
- 当前用户没有
SELECT ANY DICTIONARY或SELECT_CATALOG_ROLE,无法访问DBA_TAB_PRIVS—— 改用ALL_TAB_PRIVS(只显示当前用户可访问的对象)或USER_TAB_PRIVS(只查自己拥有的权限) -
OWNER写成了用户名而非 schema 名(例如用户SCOTT的表,OWNER是SCOTT,不是SYSTEM) - 权限是通过角色间接获得的,而
DBA_TAB_PRIVS只存直接授权 —— 角色里的权限在ROLE_TAB_PRIVS里
真正麻烦的是跨角色链路 + 对象权限嵌套,这时候单靠一张视图看不出全貌,得把 DBA_TAB_PRIVS、ROLE_TAB_PRIVS、DBA_ROLE_PRIVS 关联起来查,而且要注意循环授权可能让结果重复或发散。


















