如何快速查询Oracle数据库中具体拥有DELETE权限的用户?
- 内容介绍
- 文章标签
- 相关推荐
本文共计962个文字,预计阅读时间需要4分钟。
相关专题
直接查 dba_tab_privs 就能定位到谁有 delete 权限,但必须注意权限来源(直接授予 or 角色继承)和对象范围(全库表 or 某张表),否则容易漏人或误判。
查所有用户对任意表的DELETE权限
这是最宽泛也最常用的起点,适用于排查“谁可能删数据”:
SELECT GRANTEE, OWNER, TABLE_NAME FROM DBA_TAB_PRIVS WHERE PRIVILEGE = 'DELETE';- 结果里
GRANTEE是被授权者(可能是用户或角色),OWNER+TABLE_NAME构成具体对象 - 若只关心真实用户(排除角色),加条件
AND GRANTEE IN (SELECT USERNAME FROM DBA_USERS) - 注意:该视图不展开角色链,比如用户 A 被授了角色 R,R 有 DELETE 权,这条记录里不会出现 A —— 这是常见盲区
查某张表上所有DELETE权限持有者(含角色继承)
当发现 EMPLOYEES 表被删了,得快速锁定所有能删它的人:
- 先查直接授权:
SELECT GRANTEE FROM DBA_TAB_PRIVS WHERE OWNER='HR' AND TABLE_NAME='EMPLOYEES' AND PRIVILEGE='DELETE'; - 再查角色间接授权:用
DBA_ROLE_PRIVS和ROLE_TAB_PRIVS关联查询SELECT DISTINCT r.GRANTEE FROM DBA_ROLE_PRIVS r JOIN ROLE_TAB_PRIVS p ON r.GRANTED_ROLE = p.ROLE WHERE p.OWNER='HR' AND p.TABLE_NAME='EMPLOYEES' AND p.PRIVILEGE='DELETE'; - 两个结果集要合并,不能只看第一个 —— 很多 DBA 忘了角色这层转发
-
ROLE_TAB_PRIVS是基于角色的视图,不需要 DBA 权限就能查(当前用户有对应角色即可),但DBA_TAB_PRIVS需要 DBA 或 SELECT_CATALOG_ROLE
区分系统权限 vs 对象权限中的DELETE能力
用户不一定靠对象级 DELETE 权限来删数据,系统权限也能绕过:
-
DELETE ANY TABLE是系统权限,拥有者能删任意用户下的任意表(除了 sys/system 的核心对象) - 查法:
SELECT GRANTEE FROM DBA_SYS_PRIVS WHERE PRIVILEGE = 'DELETE ANY TABLE'; - 这类权限危害更大,且不会出现在
DBA_TAB_PRIVS中 —— 它不绑定具体表 - 注意:
DBA角色默认包含DELETE ANY TABLE,所以查DBA_ROLE_PRIVS时看到用户被授了DBA,就得立刻意识到他天然具备全局删表能力
权限查询性能与权限粒度陷阱
在大库上跑错语句可能卡住,或返回远超预期的结果:
- 避免无条件查
DBA_TAB_PRIVS(全表扫描+大量连接),务必带上OWNER或TABLE_NAME过滤 -
ALL_TAB_PRIVS只返回当前用户“可见”的对象权限(即自己拥有的,或别人授予自己的),不能替代DBA_TAB_PRIVS做全局审计 - 如果目标是审计“谁删过数据”,仅查权限不够——得结合
V$SQL、审计日志(UNIFIED_AUDIT_TRAIL)或闪回查询,权限只是前置条件 - 测试库没开审计时,权限列表就是唯一线索;但生产库应确保
AUDIT DELETE ANY TABLE BY ACCESS已启用,否则权限查得再全也看不到实际操作人
真正难的不是写出那条 SELECT,而是判断权限是否生效、是否被 REVOKE 过、是否通过嵌套角色传递,以及——权限存在但用户根本没连进来执行过。别只盯着字典视图,顺手 SELECT * FROM DBA_ROLES 看一眼角色定义,常能省掉两轮嵌套查询。
本文共计962个文字,预计阅读时间需要4分钟。
相关专题
直接查 dba_tab_privs 就能定位到谁有 delete 权限,但必须注意权限来源(直接授予 or 角色继承)和对象范围(全库表 or 某张表),否则容易漏人或误判。
查所有用户对任意表的DELETE权限
这是最宽泛也最常用的起点,适用于排查“谁可能删数据”:
SELECT GRANTEE, OWNER, TABLE_NAME FROM DBA_TAB_PRIVS WHERE PRIVILEGE = 'DELETE';- 结果里
GRANTEE是被授权者(可能是用户或角色),OWNER+TABLE_NAME构成具体对象 - 若只关心真实用户(排除角色),加条件
AND GRANTEE IN (SELECT USERNAME FROM DBA_USERS) - 注意:该视图不展开角色链,比如用户 A 被授了角色 R,R 有 DELETE 权,这条记录里不会出现 A —— 这是常见盲区
查某张表上所有DELETE权限持有者(含角色继承)
当发现 EMPLOYEES 表被删了,得快速锁定所有能删它的人:
- 先查直接授权:
SELECT GRANTEE FROM DBA_TAB_PRIVS WHERE OWNER='HR' AND TABLE_NAME='EMPLOYEES' AND PRIVILEGE='DELETE'; - 再查角色间接授权:用
DBA_ROLE_PRIVS和ROLE_TAB_PRIVS关联查询SELECT DISTINCT r.GRANTEE FROM DBA_ROLE_PRIVS r JOIN ROLE_TAB_PRIVS p ON r.GRANTED_ROLE = p.ROLE WHERE p.OWNER='HR' AND p.TABLE_NAME='EMPLOYEES' AND p.PRIVILEGE='DELETE'; - 两个结果集要合并,不能只看第一个 —— 很多 DBA 忘了角色这层转发
-
ROLE_TAB_PRIVS是基于角色的视图,不需要 DBA 权限就能查(当前用户有对应角色即可),但DBA_TAB_PRIVS需要 DBA 或 SELECT_CATALOG_ROLE
区分系统权限 vs 对象权限中的DELETE能力
用户不一定靠对象级 DELETE 权限来删数据,系统权限也能绕过:
-
DELETE ANY TABLE是系统权限,拥有者能删任意用户下的任意表(除了 sys/system 的核心对象) - 查法:
SELECT GRANTEE FROM DBA_SYS_PRIVS WHERE PRIVILEGE = 'DELETE ANY TABLE'; - 这类权限危害更大,且不会出现在
DBA_TAB_PRIVS中 —— 它不绑定具体表 - 注意:
DBA角色默认包含DELETE ANY TABLE,所以查DBA_ROLE_PRIVS时看到用户被授了DBA,就得立刻意识到他天然具备全局删表能力
权限查询性能与权限粒度陷阱
在大库上跑错语句可能卡住,或返回远超预期的结果:
- 避免无条件查
DBA_TAB_PRIVS(全表扫描+大量连接),务必带上OWNER或TABLE_NAME过滤 -
ALL_TAB_PRIVS只返回当前用户“可见”的对象权限(即自己拥有的,或别人授予自己的),不能替代DBA_TAB_PRIVS做全局审计 - 如果目标是审计“谁删过数据”,仅查权限不够——得结合
V$SQL、审计日志(UNIFIED_AUDIT_TRAIL)或闪回查询,权限只是前置条件 - 测试库没开审计时,权限列表就是唯一线索;但生产库应确保
AUDIT DELETE ANY TABLE BY ACCESS已启用,否则权限查得再全也看不到实际操作人
真正难的不是写出那条 SELECT,而是判断权限是否生效、是否被 REVOKE 过、是否通过嵌套角色传递,以及——权限存在但用户根本没连进来执行过。别只盯着字典视图,顺手 SELECT * FROM DBA_ROLES 看一眼角色定义,常能省掉两轮嵌套查询。

