Oracle在9i提供了在线重定义功能,利用这个功能可以在线修改表的逻辑结构或物理结构。不过在10g以前的版本,原表上的所有的索引、触发器、约束、统计信息和权限都需要在目标表上手工创建,不过从10g开始,Oracle提供了新的过程COPY_TABLE_DEPENDENTS,大大简化了在线重定义的步骤。
9i中使用在线重定义的例子:http://yangtingkun.itpub.net/post/468/12962
通过10g的COPY_TABLE_DEPENDENTS过程,极大的简化了在线重定义所需要的手工处理部分,一个包含索引、约束、触发器、统计信息和授权的表的在线重定义过程,只需要下面的步骤就可以完成:
SQL> CREATE TABLE T AS SELECT ROWNUM ID, A.* FROM USER_OBJECTS A;
表已创建。
SQL> ALTER TABLE T ADD PRIMARY KEY (ID);
表已更改。
SQL> ALTER TABLE T ADD CHECK (ID > 0);
表已更改。
SQL> GRANT INSERT ON T TO SYSTEM;
授权成功。
SQL> CREATE INDEX IND_T_NAME ON T (OBJECT_NAME);
索引已创建。
SQL> CREATE OR REPLACE TRIGGER TRI_T BEFORE INSERT ON T FOR EACH ROW
2 BEGIN
3 NULL;
4 END;
5 /
触发器已创建
SQL> EXEC DBMS_STATS.GATHER_TABLE_STATS(USER, 'T')
PL/SQL 过程已成功完成。
SQL> CREATE TABLE T_INTER PARTITION BY HASH (ID)
2 PARTITIONS 4
3 AS SELECT ROWNUM ID, A.* FROM USER_OBJECTS A WHERE 1 = 2;
表已创建。
初始表已经准备好了,准备改成的分区表也已经建立成功,下面开始在线重定义过程:
SQL> SET SERVEROUT ON SIZE 1000000
SQL> BEGIN
2 DBMS_REDEFINITION.CAN_REDEF_TABLE(USER, 'T');
3 END;
4 /
PL/SQL 过程已成功完成。
SQL> BEGIN
2 DBMS_REDEFINITION.START_REDEF_TABLE(USER, 'T', 'T_INTER');
3 END;
4 /
PL/SQL 过程已成功完成。
SQL> VAR V_NUM NUMBER
SQL> BEGIN
2 DBMS_REDEFINITION.COPY_TABLE_DEPENDENTS(USER, 'T', 'T_INTER',
3 DBMS_REDEFINITION.CONS_ORIG_PARAMS, TRUE, TRUE, TRUE, TRUE, :V_NUM, TRUE);
4 END;
5 /
PL/SQL 过程已成功完成。
SQL> PRINT V_NUM
V_NUM
----------
0
SQL> BEGIN
2 DBMS_REDEFINITION.FINISH_REDEF_TABLE(USER, 'T', 'T_INTER');
3 END;
4 /
PL/SQL 过程已成功完成。
在线重定义操作已经完成,下面可以检查索引、约束、权限、触发器和统计信息是否已经被成功克隆:
SQL> SELECT TABLE_NAME, INDEX_NAME FROM USER_INDEXES WHERE TABLE_NAME IN ('T', 'T_INTER');
TABLE_NAME INDEX_NAME
------------------------------ ------------------------------
T SYS_C006293
T IND_T_NAME
T_INTER TMP$$_SYS_C0062930
T_INTER TMP$$_IND_T_NAME0
SQL> SELECT TABLE_NAME, CONSTRAINT_NAME, CONSTRAINT_TYPE
2 FROM USER_CONSTRAINTS WHERE TABLE_NAME IN ('T', 'T_INTER');
TABLE_NAME CONSTRAINT_NAME C
------------------------------ ------------------------------ -
T SYS_C006294 C
T SYS_C006293 P
T_INTER TMP$$_SYS_C0062930 P
T_INTER TMP$$_SYS_C0062940 C
SQL> SELECT TABLE_NAME, TRIGGER_NAME FROM USER_TRIGGERS WHERE TABLE_NAME IN ('T', 'T_INTER');
TABLE_NAME TRIGGER_NAME
------------------------------ ------------------------------
T TRI_T
T_INTER TMP$$_TRI_T0
SQL> SELECT TABLE_NAME, PRIVILEGE FROM USER_TAB_PRIVS WHERE TABLE_NAME IN ('T', 'T_INTER');
TABLE_NAME PRIVILEGE
------------------------------ ----------------------------------------
T_INTER INSERT
T INSERT
SQL> SELECT TABLE_NAME, NUM_ROWS FROM USER_TABLES WHERE TABLE_NAME IN ('T', 'T_INTER');
TABLE_NAME NUM_ROWS
------------------------------ ----------
T 34
T_INTER 34
SQL> SELECT TABLE_NAME, PARTITION_NAME FROM USER_TAB_PARTITIONS
2 WHERE TABLE_NAME IN ('T', 'T_INTER');
TABLE_NAME PARTITION_NAME
------------------------------ ------------------------------
T SYS_P41
T SYS_P42
T SYS_P43
T SYS_P44
SQL> DROP TABLE T_INTER PURGE;
表已删除。
所有的表相关对象已经创建成功,且在线重定义操作也顺利完成,最后删除中间表即可。