查某张表被谁授了权限必须指定OWNER,否则不同schema下同名表会导致结果混杂;正确写法是SELECT GRANTEE,GRANTOR,PRIVILEGE,GRANTABLE,HIERARCHY FROM DBA_TAB_PRIVS WHERE OWNER='SCOTT' AND TABLE_NAME='EMP'。
查某张表被谁授了权限,必须指定 OWNER
直接 select * from dba_tab_privs where table_name = 'emp' 极大概率查出一堆记录——因为不同 schema(比如 scott、hr、ops)下可能都有叫 emp 的表。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:允许修改表结构(如加列、改类型),比SELECT危险得多,却常被当作低危权限放行
查权限时若只盯着 SELECT 就停了,很可能漏掉真实的数据链路和变更风险。


















