不会。ALTER TABLE ... ALLOCATE EXTENT 不触发延迟段创建,且在无段时直接报错 ORA-01658;它仅用于扩展现有段,不能创建初始段。
ALTER TABLE ... ALLOCATE EXTENT 会触发延迟段创建吗?
不会。延迟段创建(deferred segment creation)是 oracle 11.2+ 的默认行为,意味着 create table 时不分配任何物理段,直到第一次 insert 或显式调用 allocate extent。但注意:alter table ... allocate extent 在表尚未有段时会直接失败,报错 ora-01658: cannot create initial extent for segment in tablespace —— 因为它不负责“建段”,只负责“扩段”。
怎么让空表立刻有段(绕过延迟段创建)?
必须在建表后、首次插入前,用能强制生成段的 DDL 操作。最可靠的是:
-
ALTER TABLE table_name ALLOCATE EXTENT不行(如上所述,会报错) -
INSERT INTO table_name VALUES (...); ROLLBACK;可行,但需有至少一列可插入(比如NOT NULL列),且事务开销不必要 - 更干净的做法:用
ALTER TABLE table_name MOVE TABLESPACE users;—— 它要求表已有段,所以 Oracle 会先隐式创建段再执行 move;但如果表真没段,它也会失败 - 真正兜底方案:
EXEC DBMS_SPACE_ADMIN.TABLESPACE_MIGRATE_TO_LOCAL('TABLESPACE_NAME');不相关,别乱用 - 正确答案:
ALTER TABLE table_name ALLOCATE EXTENT加SEGMENT CREATION IMMEDIATE修饰 —— 但这是建表时的选项,不是 ALTER 时的
所以,唯一可控、无副作用、无需插入数据的方式,是在 CREATE TABLE 时就禁用延迟段:
CREATE TABLE t1 (id NUMBER) SEGMENT CREATION IMMEDIATE;
如果表已存在且没段,现在想补段怎么办?
Oracle 不提供 “补段” 的标准 DDL 命令。你只能靠“触发段创建”的副作用操作。实测有效且安全的方法只有两个:
-
INSERT一行再ROLLBACK(需满足约束、有合适值) -
ALTER TABLE table_name MODIFY (some_col VARCHAR2(100) DEFAULT 'x');—— 改列默认值会触发段创建(Oracle 内部机制),且不改数据、不锁表(12c+)
注意:ALTER TABLE ... ADD COLUMN DEFAULT ... 也有效,但会加列;MODIFY DEFAULT 更轻量。别用 SHRINK SPACE 或 REBUILD,它们都要求段已存在。
为什么不能用 DBMS_SPACE 或 DBMS_SEGADM 强制分配?
这些包里的过程(比如 DBMS_SPACE.CREATE_SEGMENT)是内部使用、未公开、无文档支持的,调用可能报 PLS-00201: identifier must be declared 或直接 ORA-30511。官方明确不承诺兼容性,生产环境踩了就是白忙活。延迟段创建本身是优化,强行绕过它往往说明设计有问题——比如依赖 dba_extents 立即查到表信息,其实该查 dba_tables.segment_created 字段判断状态。
段是否创建,本质是 dba_tables.segment_created 字段值('YES'/'NO'),而不是有没有 extent。很多脚本误以为查不到 dba_extents 就等于表异常,其实只是还没触发创建而已。










