要查某张表被哪些用户/角色授了权限,必须指定owner,如select grantee,grantor,privilege,grantable,hierarchy from dba_tab_privs where owner='scott' and table_name='emp';否则可能因同名表跨schema导致结果混乱。
查某张表被哪些用户/角色授了权限,必须指定 owner
直接 select * from dba_tab_privs where table_name = 'emp' 很可能查出多条记录——因为不同 schema(如 scott、hr、ops)下可能都有叫 emp 的表。oracle 不会自动帮你限定 schema,必须显式写上 owner 字段。
正确写法示例:
SELECT GRANTEE, GRANTOR, PRIVILEGE, GRANTABLE, HIERARCHY FROM DBA_TAB_PRIVS WHERE OWNER = 'SCOTT' AND TABLE_NAME = 'EMP';
-
GRANTEE可能是具体用户名、角色名,也可能是PUBLIC(需特别警惕) -
GRANTABLE = 'YES'表示该权限可被再授予他人,属于高风险配置 -
HIERARCHY = 'YES'仅对SELECT等少数权限有意义,且依赖细粒度访问控制(FGAC)启用状态,日常排查通常可忽略
查不到结果?先确认三件事
权限确实存在但查不到,90% 是权限视图访问或过滤条件问题:
- 当前用户没有
SELECT ANY DICTIONARY或SELECT_CATALOG_ROLE,无法访问DBA_TAB_PRIVS—— 改用ALL_TAB_PRIVS(只显示你有权访问的对象)或USER_TAB_PRIVS(只查你自己被授的权限) -
OWNER写成了用户名而非 schema 名。例如:用户SCOTT创建的表,OWNER是'SCOTT',不是'SYSTEM'或当前登录用户 - 表名默认大写,除非建表时用了双引号(如
"emp"),否则不能写成小写'emp';大小写不敏感的是权限名(如'select'和'SELECT'都行)
GRANTEE 是角色时,权限不会自动展开
DBA_TAB_PRIVS 只存「谁被授了什么」,不反映「谁实际能用」。如果 GRANTEE 是角色(如 'APP_ROLE'),而你想知道最终哪些用户能访问这张表,不能只查这一张表。
需要递归关联:
- 先查角色成员:
SELECT GRANTEE FROM DBA_ROLE_PRIVS WHERE GRANTED_ROLE = 'APP_ROLE' - 再查这些用户是否拥有该角色为
DEFAULT_ROLE = 'YES'(否则需手动SET ROLE才生效) - 注意:
DBA_ROLE_PRIVS中的ADMIN_OPTION和DEFAULT_ROLE是两个独立字段,别混淆
容易被忽略的权限类型:REFERENCES 和 ALTER
除了常见的 SELECT/INSERT/UPDATE/DELETE,以下权限常被漏查但影响关键:
-
REFERENCES:允许在其他表上创建外键指向该表,构成隐式数据依赖,迁移或下线表前必须确认 -
ALTER:允许修改表结构(如加列、改类型),比SELECT危险得多,却常被当作低危权限放行 -
INDEX:允许在表上建索引,虽不直接读写数据,但可能被用于侧信道攻击或性能干扰
这些权限在 DBA_TAB_PRIVS 中统一存在 PRIVILEGE 列,但语义差异大,不能一概而论。查权限时建议显式列出所有可能值,而不是只过滤常见几个。











