ora-01952报错是因为用户未被直接授予该系统权限,只能通过角色继承获得;必须先查dba_sys_privs确认直授权限,否则需从角色层面回收,如revoke role_name from user或revoke create table from role_name(需admin option)。

直接执行 REVOKE 为什么常报 ORA-01952?
因为 Oracle 不允许对“未被直接授予”的权限执行 REVOKE。比如用户 SCOTT 没有被你亲手授过 CREATE TABLE,而是通过角色 RESOURCE 继承来的,那么 REVOKE CREATE TABLE FROM SCOTT 就会失败,报 ORA-01952: system privilege not granted。
真正有效的做法是先确认权限来源:
- 查该用户直接受到的系统权限:
SELECT * FROM dba_sys_privs WHERE grantee = 'SCOTT' - 查该用户拥有的角色:
SELECT granted_role FROM dba_role_privs WHERE grantee = 'SCOTT' - 查角色包含哪些系统权限:
SELECT * FROM role_sys_privs WHERE role = 'RESOURCE'
只有在第一行查询结果里出现的权限,才能用 REVOKE 直接回收;否则得从角色入手。
回收来自角色的权限,该撤角色还是撤角色里的权限?
取决于管控目标:
- 如果只是想禁用某类能力(如不让建表),且该能力集中在一个自定义角色里,就
REVOKE role_name FROM user - 如果想保留角色其他权限(如
CREATE SESSION),只去掉其中某个系统权限(如CREATE TABLE),而你又有ADMIN OPTION,可以REVOKE CREATE TABLE FROM role_name - 对 Oracle 内置角色如
RESOURCE,不建议修改其定义——它默认带UNLIMITED TABLESPACE,改了可能影响其他用户;更稳妥的是新建一个精简角色替代它
注意:REVOKE 对角色本身不级联,即撤掉角色不会自动清理用户已用该角色创建的对象(如表、视图)。
UNLIMITED TABLESPACE 回收后为什么立刻报 ORA-01536?
因为回收该权限后,用户在所有表空间的配额立即变为 0,包括其 DEFAULT TABLESPACE。哪怕只建一张小表,也会触发 ORA-01536: space quota exceeded for tablespace 'USERS'。
必须紧接着补配额:
- 给默认表空间设有限配额:
ALTER USER scott QUOTA 10M ON users - 或仅放开特定表空间:
ALTER USER scott QUOTA UNLIMITED ON data_tbs - 别漏
TEMP表空间——虽然不存数据,但排序失败会导致 SQL 执行中断
如果之后又 GRANT RESOURCE TO scott,UNLIMITED TABLESPACE 会自动回来,等于白操作。
脚本批量回收时最容易忽略的三个点
生成一堆 REVOKE ... FROM ... 语句不难,但落地失效往往因为:
- 没排除
SYS、SYSTEM等内置账户——它们需要保留部分高危权限,硬回收可能导致实例异常 - 没检查用户当前是否活跃:
SELECT username FROM v$session WHERE username = 'SCOTT';回收不影响已有会话,但新连接立即受限,可能引发应用报错 - 没验证回收后权限是否真消失:回收后应立刻用该用户连库测试关键操作(如
CREATE TABLE),而不是只看dba_sys_privs是否清空——角色继承的权限仍可能生效
真正的回收闭环不是“执行一次 REVOKE”,而是“查来源 → 精准撤权 → 补配额/换角色 → 验证行为”。权限一旦松动,再收紧就比从零建模难得多。











