不能。ALTER USER ... DEFAULT TABLESPACE 仅影响后续新建对象,对已有表、索引、LOB等完全不生效;必须用 ALTER TABLE MOVE、ALTER INDEX REBUILD 等逐个迁移。
ALTER USER ... DEFAULT TABLESPACE 能不能直接迁移已有对象?
不能。执行 alter user username default tablespace new_ts 只影响后续新创建的对象(比如新建的表、索引),对用户已存在的表、索引、lob段等**完全不生效**。这是最常被误解的一点——设了默认表空间≠自动搬数据。
如何批量移动表和索引到新表空间?
Oracle 没有“一键迁移用户全部对象”的 ALTER 命令,必须逐个对象操作。核心是用 ALTER TABLE 和 ALTER INDEX 的 MOVE / REBUILD 子句:
-
ALTER TABLE t1 MOVE TABLESPACE new_ts;—— 移动堆表(含行数据),但不移动索引 -
ALTER INDEX i1 REBUILD TABLESPACE new_ts;—— 重建索引到新表空间 - LOB 列需单独处理:
ALTER TABLE t1 MOVE LOB(lob_col) STORE AS (TABLESPACE new_ts); - 分区表要按分区/子分区操作,不能直接对表级 MOVE
注意:MOVE 和 REBUILD 都会锁表、产生大量 redo/undo,建议在低峰期执行;如果表有主键或依赖约束,重建索引前确认约束状态(ENABLED 或 DISABLED)。
为什么不能只改用户默认表空间就完事?
因为 Oracle 中「对象物理存储位置」由创建时指定的 TABLESPACE 属性决定,该属性固化在数据字典(如 DBA_TABLES.TABLESPACE_NAME)中,不会随用户默认值变更而更新。查看当前分布可用:
SELECT segment_type, segment_name, tablespace_name FROM dba_segments WHERE owner = 'USERNAME';
常见误操作:改完 DEFAULT TABLESPACE 就以为迁移完成,结果发现 DBA_SEGMENTS 里 90% 的表还在旧表空间——这时必须手动触发 MOVE/REBUILD。
自动化脚本生成要注意什么?
可以用查询拼出批量 DDL,但必须人工审核再执行:
- 排除系统对象(如以
BIN$开头的回收站对象) - 跳过 IOT 的溢出段(
OVERFLOW),它需单独 MOVE - 区分临时段、回滚段——它们不归用户所有,不能 ALTER
- 含 LONG 或未加密列的表,MOVE 可能失败,需先转为 LOB
典型生成语句:
SELECT 'ALTER TABLE ' || segment_name || ' MOVE TABLESPACE new_ts;' FROM dba_segments WHERE owner = 'U1' AND segment_type = 'TABLE' AND tablespace_name != 'new_ts';
真正麻烦的不是语法,而是判断哪些对象可安全移动、哪些依赖关系要先处理(比如物化视图日志、函数索引的底层函数权限)、以及移动后是否要重收集统计信息——这些没法靠一条 ALTER 解决。











