直接执行ALTER TABLE ... MOVE TABLESPACE会使所有索引失效且不迁移LOB字段;必须手动重建索引(ALTER INDEX ... REBUILD)并显式指定LOB子句(如LOB(col) STORE AS(TABLESPACE ...)),分区表需按分区/子分区逐个MOVE,12c+支持ONLINE但有约束。
直接执行 alter table ... move tablespace 会失效所有索引,且不处理 lob 字段——这是最常被跳过的致命点。
普通表迁移:MOVE 后必须重建索引
Oracle 的 MOVE 不是“搬家”,而是重建整个表段(新分配区、重写数据块),原索引指向的物理地址全部作废。执行后查 user_indexes.status 会看到全是 'UNUSABLE'。
- 先移动表:
ALTER TABLE t1 MOVE TABLESPACE users; - 再重建索引:
ALTER INDEX idx_t1_col1 REBUILD TABLESPACE users; - 批量生成语句(在目标用户下):
SELECT 'ALTER INDEX ' || index_name || ' REBUILD TABLESPACE users;' FROM user_indexes WHERE status = 'UNUSABLE'; - Oracle 12c+ 支持
UPDATE INDEXES子句,但仅对部分索引类型生效(如本地索引),且不能和LOB子句共用,慎用
含 LOB 字段的表:MOVE 必须显式声明 LOB 子句
只写 MOVE TABLESPACE,LOB 段(CLOB/BLOB)仍留在原表空间,表空间实际没腾出空间,还可能引发后续 ORA-22922: nonexistent LOB value 错误。
- 正确写法(单个 LOB 字段):
ALTER TABLE t1 MOVE TABLESPACE users LOB (content) STORE AS (TABLESPACE users); - 多个 LOB 字段需逐个列出:
LOB (c1, c2, c3),不能用通配符 - 若要禁用行内存储(避免小 LOB 挤占数据块):
DISABLE STORAGE IN ROW加在STORE AS后 - 注意:
LONG类型不支持MOVE,必须先转为CLOB再操作
分区表迁移:不能对表整体 MOVE,必须按分区操作
对分区表直接执行 ALTER TABLE ... MOVE TABLESPACE 会报错:ORA-14511: cannot perform operation on a partitioned object。
- 迁移单个分区:
ALTER TABLE t1 MOVE PARTITION p202401 TABLESPACE users; - 迁移子分区:
ALTER TABLE t1 MOVE SUBPARTITION sp_jan_01 TABLESPACE users; - 12.1+ 支持
ONLINE迁移分区,加UPDATE INDEXES可自动重建本地索引(全局索引仍需手动REBUILD) - 迁移完成后,建议更新默认属性:
ALTER TABLE t1 MODIFY DEFAULT ATTRIBUTES FOR PARTITION p202401 TABLESPACE users;,避免新增分区落回旧表空间
执行前必须检查的三项风险
生产环境跑脚本前漏掉任意一项,都可能导致长时间锁表或不可逆损坏。
- 确认表不是
SYSTEM、SYSAUX、UNDO等系统表空间对象:SELECT table_name, tablespace_name FROM user_tables WHERE tablespace_name IN ('SYSTEM', 'SYSAUX', 'UNDO'); - 检查是否有
DISABLED或UNUSABLE索引/约束,MOVE 后它们不会自动恢复 - 表名含大小写或特殊字符(如
"MyTable")时,生成脚本中必须用双引号包裹,否则报ORA-00942
真正麻烦的从来不是命令本身,而是 MOVE 后那一堆散落各处的索引、LOB 段、分区默认值和权限依赖——它们不会自动跟着走,得你一条条盯住。


















