不安全,select any table是高危系统级权限,可读取所有用户(含sys)任意表并用于提权;应严格遵循最小权限原则,按需授予具体对象权限或角色,误授后须及时回收并检查依赖对象。
直接授予 select any table 权限是否安全?
不建议直接授予 select any table,它允许用户查询数据库中所有用户的表(包括 sys、system 等系统对象),存在严重数据泄露风险。生产环境几乎从不启用该权限,审计时也极易被标记为高危配置。
更可控的替代方案:基于角色 + 数据字典动态授权
实际需求往往是“查本用户能访问的所有业务表”,而非“查整个库”。推荐用角色封装 + DBA_TAB_PRIVS 或 ALL_TAB_PRIVS 查找已授出的查询权限,再批量授予:
- 先创建专用角色:
CREATE ROLE read_only_role; - 把当前 schema 下所有表的
SELECT权限批量授给该角色:DECLARE CURSOR c IS SELECT table_name FROM user_tables; BEGIN FOR r IN c LOOP EXECUTE IMMEDIATE 'GRANT SELECT ON ' || r.table_name || ' TO read_only_role'; END LOOP; END; - 最后把角色授予目标用户:
GRANT read_only_role TO user_a;
如果必须跨 schema 查询,该怎么授权?
常见于报表用户需查多个业务 schema 的表。此时应避免 SELECT ANY TABLE,改用显式授权:
- 逐个 schema 授权(最安全):
GRANT SELECT ON schema_b.orders TO user_rpt; - 用 PL/SQL 批量生成授权语句(注意检查
schema_b下哪些表真需要开放):SELECT 'GRANT SELECT ON schema_b.' || table_name || ' TO user_rpt;' FROM dba_tables WHERE owner = 'SCHEMA_B' AND temporary = 'N';
- 切勿用
GRANT SELECT ON schema_b.* TO ...—— Oracle 不支持通配符授权语法,会报错ORA-00905: missing keyword
为什么视图或同义词不能绕过权限检查?
有人试图建视图包装多张表来“简化授权”,但视图执行仍受底层表权限约束。即使你有 CREATE VIEW 权限,查询该视图时仍会触发对原表的 SELECT 权限校验。同理,同义词只是别名,不改变权限模型。
真正省事的做法是:让 DBA 把常用跨 schema 查询逻辑封装成带 DEFINER'S RIGHT 的存储过程,并显式授予执行权限——这样调用者只需 EXECUTE 权限,无需底层表的 SELECT。
权限粒度越细,后期排查越容易;一次性放开的权限,往往就是下次数据误查的起点。











