oracle不支持列级权限的精准撤销,只能整表撤销再重授所需列;撤销时若存在依赖对象(如视图)会报ora-01720错误,需先清理依赖;revoke all会级联撤销下游转授权限,风险高于单独撤销update。
直接执行 revoke update on table_name from user_name 即可,不需要先撤全部再重授。但必须注意:oracle 不支持“部分列级权限的精准撤销”,且对象权限撤销会触发级联影响。
为什么不能只 revoke 某几列的 UPDATE 权限
Oracle 的 REVOKE 语句不支持列粒度的对象权限撤销。比如你曾用 GRANT UPDATE (ename, sal) ON emp TO scott 授予了两列更新权,现在想只收回 sal 列的权限——这是做不到的。
你只能:
• 先执行 REVOKE UPDATE ON emp FROM scott(整张表的 UPDATE 全撤)
• 再执行 GRANT UPDATE (ename) ON emp TO scott(重新授回需要的列)
执行 REVOKE UPDATE 时常见的中断报错
如果目标用户 scott 已基于该表创建了视图、函数或包体,REVOKE UPDATE ON hr.employees FROM scott 可能直接失败,报 ORA-01720: grant option does not exist for 'HR.EMPLOYEES'。
这不是语法错误,而是 Oracle 强制要求你先清理依赖:
- 查依赖:运行
SELECT NAME, TYPE FROM ALL_DEPENDENCIES WHERE REFERENCED_OWNER = 'HR' AND REFERENCED_NAME = 'EMPLOYEES' AND OWNER != 'HR' - 若返回
TYPE = VIEW,需让scott自行DROP VIEW v_emp,或 DBA 临时CREATE OR REPLACE VIEW v_emp AS SELECT * FROM dual断开引用 - 切勿跳过这步直接重试——权限状态会处于不一致中间态
保留 SELECT 权限的典型误操作
有人为“保险起见”先跑 REVOKE ALL ON hr.employees FROM scott,再 GRANT SELECT ON hr.employees TO scott。这看似稳妥,实则多此一举且风险更高:
• REVOKE ALL 会连带撤掉 REFERENCES、INSERT、DELETE 等所有权限,但若用户正在执行 DML 事务,可能被强制中断
• 更关键的是:如果该用户之前用 WITH GRANT OPTION 把 SELECT 转授给了别人,REVOKE ALL 会一并收回下游权限(Oracle 对象权限是级联撤销的),而单独 REVOKE UPDATE 不会影响已转授的 SELECT
确认权限是否生效的验证方式
别只查 DBA_TAB_PRIVS,它只显示当前授予状态,不反映实际可用性。真正有效的方式是模拟用户操作:
• 切换到 scott 用户:CONNECT scott/password
• 测试读:SELECT * FROM hr.employees WHERE ROWNUM = 1(应成功)
• 测试写:UPDATE hr.employees SET ename = 'X' WHERE empno = 7369(应报 ORA-01031: insufficient privileges)
• 特别注意:如果表上有 INSTEAD OF 触发器或 VPD 策略,UPDATE 可能表面报错但实际被拦截,此时需检查 ALL_TRIGGERS 和 DBA_POLICIES
真正麻烦的从来不是那条 REVOKE 语句本身,而是依赖对象没清理干净,或者误以为列级权限能被单独撤销。











