根本原因是oracle默认禁止非sys用户向system表空间写入,因其专用于数据字典和系统对象;即使有create table权限,也因无配额(quota为0且不可授予)而报ora-01950。
用户在 system 表空间创建表、索引等对象失败,根本原因不是“没登录”或“没建表权限”,而是 oracle 严格限制普通用户使用 system 表空间——它专供数据字典和系统对象,**默认禁止任何非sys用户写入**。强行指定 system 作为默认表空间或显式指定 tablespace system,大概率触发 ora-01950: no privileges on tablespace 'system'。
为什么不能在 SYSTEM 表空间建对象
SYSTEM 是 Oracle 内置的、只读保护级别的核心表空间,存放数据字典视图(如 DBA_TABLES)、系统回滚段、内置包(STANDARD, DBMS_*)等。即使你拥有 CREATE TABLE 权限,Oracle 也会在对象创建前校验:当前用户是否被显式授予了该表空间的配额(QUOTA)。而 SYSTEM 表空间的配额对非 SYS 用户默认为 0,且无法通过 ALTER USER ... QUOTA 赋予(会报 ORA-02181 或静默忽略)。
-
SYS用户可以操作SYSTEM,但这是维护行为,不应用于日常开发 -
SYSTEM用户虽名字相似,但默认也不具备在SYSTEM表空间建对象的配额 - 试图用
GRANT UNLIMITED TABLESPACE TO user也不能绕过该限制——该权限对SYSTEM和SYSAUX无效
如何确认当前用户正试图往 SYSTEM 写入
常见触发场景包括:CREATE TABLE t(x INT) 没指定表空间,且用户默认表空间是 SYSTEM;或显式写了 CREATE TABLE t(x INT) TABLESPACE SYSTEM。可通过以下方式快速定位:
- 查用户默认表空间:
SELECT default_tablespace FROM dba_users WHERE username = 'YOUR_USER'; - 查用户在各表空间的配额:
SELECT tablespace_name, bytes/1024/1024 MB FROM dba_ts_quotas WHERE username = 'YOUR_USER';—— 若结果里没有SYSTEM行,或BYTES为 0,即无写入能力 - 执行建表语句时加
/*+ APPEND */或指定TABLESPACE SYSTEM,会直接暴露意图
正确做法:切换到常规用户表空间
必须让对象落在非系统表空间(如 USERS、EXAMPLE 或自建的 APP_DATA)。有两条路径:
- 修改用户默认表空间(推荐):
ALTER USER your_user DEFAULT TABLESPACE users;,再确保已分配配额:ALTER USER your_user QUOTA UNLIMITED ON users; - 建表时显式指定(临时救急):
CREATE TABLE t(x INT) TABLESPACE users;—— 但注意,如果用户在users表空间仍无配额,仍会报ORA-01950 - 验证是否生效:
CREATE TABLE test_check (id NUMBER);不带TABLESPACE子句,成功即说明默认表空间已切换且配额有效
容易被忽略的关键点
很多 DBA 会下意识给用户授 UNLIMITED TABLESPACE 就以为万事大吉,但这个权限对 SYSTEM 和 SYSAUX 完全不生效;更隐蔽的是,有些脚本或 ORM(如旧版 Hibernate)会硬编码 TABLESPACE SYSTEM,导致部署时突然失败;还有一种情况:用户被误设为 DEFAULT TABLESPACE SYSTEM 后,连 CREATE SESSION 都可能卡住(尤其在资源计划启用时)。真正安全的做法,是把所有业务用户彻底隔离出 SYSTEM 和 SYSAUX,哪怕只是检查一遍 dba_users.default_tablespace 字段。











