必须显式指定owner,否则因table_name非唯一且oracle不自动推断schema,会导致查出多条无关记录、误判权限;还需注意大小写规则、grantee为角色时需追溯成员及默认角色状态、访问权限不足时换用all_/user_tab_privs视图。

查某张表被哪些用户/角色授了权限,必须指定 OWNER
直接 SELECT * FROM DBA_TAB_PRIVS WHERE TABLE_NAME = 'EMP' 很可能返回几十条记录——因为不同 schema(如 SCOTT、HR、OPS)下都可能存在同名表。Oracle 不会自动按当前登录用户或上下文限定 owner,必须显式写上 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:允许修改表结构(如增删列、改约束),一旦被误授,可能破坏应用一致性
这两类权限在 DBA_TAB_PRIVS.PRIVILEGE 列中明确标出,但因不常用于日常查询,容易在权限审计中被跳过。











