9i的在线重定义存在一个问题,执行完在线重定义后,表的名称虽然保持不变,但是索引、约束、触发器等关联对象的名称会发生变化,有时候这会带来一定的问题,而要在事后手工修改,会比较麻烦。
10g的在线重定义解决这个问题。如果对象是利用COPY_TABLE_DEPENDENTS创建的,那么这些关联的对象在重定义操作完成后,自动改为原始的名称。如果是手工创建的关联对象,则可以利用REGISTER_DEPENDENT_OBJECT过程,所有执行了REGISTER_DEPENDENT_OBJECT过程的关联对象,都会在重定义操作完成后自动重命名。
这篇文章来看REGISTER_DEPENDENT_OBJECT的例子。
上一篇介绍了10g中COPY_TABLE_DEPENDENTS的例子,这篇看看手工创建关联对象,然后使用REGISTER_DEPENDENT_OBJECT的例子。
首先还是先看9i的例子:
SQL> SELECT * FROM V$VERSION;
BANNER
----------------------------------------------------------------
Oracle9i Enterprise Edition Release9.2.0.4.0 -Production
PL/SQL Release 9.2.0.4.0 - Production
CORE 9.2.0.3.0 Production
TNS for 32-bit Windows: Version 9.2.0.4.0 - Production
NLSRTL Version 9.2.0.4.0 - Production
SQL> CREATE TABLE T AS SELECT ROWNUM ID, A.* FROM USER_OBJECTS A;
表已创建。
SQL> ALTER TABLE T ADD CONSTRAINT PK_T PRIMARY KEY (ID);
表已更改。
SQL> ALTER TABLE T ADD CHECK (ID > 0);
表已更改。
SQL> CREATE INDEX IND_T_NAME ON T (OBJECT_NAME);
索引已创建。
SQL> CREATE OR REPLACE TRIGGER TRI_T
2 BEFORE INSERT ON T
3 FOR EACH ROW
4 BEGIN
5 NULL;
6 END;
7 /
触发器已创建
SQL> CREATE TABLE T_INTER
2 PARTITION BY HASH (ID)
3 PARTITIONS 4
4 AS SELECT ROWNUM ID, A.*
5 FROM USER_OBJECTS A
6 WHERE 1 = 2;
表已创建。
SQL> ALTER TABLE T_INTER ADD CONSTRAINT PK_T_INTER PRIMARY KEY (ID);
表已更改。
SQL> ALTER TABLE T_INTER ADD CHECK (ID > 0) DISABLE;
表已更改。
SQL> CREATE INDEX IND_T_INTER_NAME ON T_INTER (OBJECT_NAME);
索引已创建。
SQL> CREATE OR REPLACE TRIGGER TRI_T_INTER
2 BEFORE INSERT ON T_INTER
3 FOR EACH ROW
4 BEGIN
5 NULL;
6 END;
7 /
触发器已创建
SQL> SET SERVEROUT ON SIZE 1000000
SQL> EXEC DBMS_REDEFINITION.CAN_REDEF_TABLE(USER, 'T')
PL/SQL过程已成功完成。
SQL> EXEC DBMS_REDEFINITION.START_REDEF_TABLE(USER, 'T', 'T_INTER')
PL/SQL过程已成功完成。
SQL> SELECT TABLE_NAME, INDEX_NAME
2 FROM USER_INDEXES
3 WHERE TABLE_NAME IN ('T', 'T_INTER');
TABLE_NAME INDEX_NAME
------------------------------ ------------------------------
T_INTER IND_T_INTER_NAME
T IND_T_NAME
T PK_T
T_INTER PK_T_INTER
SQL> SELECT TABLE_NAME, CONSTRAINT_NAME
2 FROM USER_CONSTRAINTS
3 WHERE TABLE_NAME IN ('T', 'T_INTER');
TABLE_NAME CONSTRAINT_NAME
------------------------------ ------------------------------
T PK_T
T SYS_C002990
T_INTER PK_T_INTER
T_INTER SYS_C002992
SQL> SELECT TABLE_NAME, TRIGGER_NAME
2 FROM USER_TRIGGERS
3 WHERE TABLE_NAME IN ('T', 'T_INTER');
TABLE_NAME TRIGGER_NAME
------------------------------ ------------------------------
T TRI_T
T_INTER TRI_T_INTER
SQL> EXEC DBMS_REDEFINITION.FINISH_REDEF_TABLE(USER, 'T', 'T_INTER')
PL/SQL过程已成功完成。
SQL> SELECT TABLE_NAME, INDEX_NAME
2 FROM USER_INDEXES
3 WHERE TABLE_NAME IN ('T', 'T_INTER');
TABLE_NAME INDEX_NAME
------------------------------ ------------------------------
T IND_T_INTER_NAME
T_INTER IND_T_NAME
T_INTER PK_T
T PK_T_INTER
SQL> SELECT TABLE_NAME, CONSTRAINT_NAME
2 FROM USER_CONSTRAINTS
3 WHERE TABLE_NAME IN ('T', 'T_INTER');
TABLE_NAME CONSTRAINT_NAME
------------------------------ ------------------------------
T PK_T_INTER
T SYS_C002992
T_INTER PK_T
T_INTER SYS_C002990
SQL> SELECT TABLE_NAME, TRIGGER_NAME
2 FROM USER_TRIGGERS
3 WHERE TABLE_NAME IN ('T', 'T_INTER');
TABLE_NAME TRIGGER_NAME
------------------------------ ------------------------------
T_INTER TRI_T
T TRI_T_INTER
SQL> DROP TABLE T_INTER;
表已删除。
可以看到,执行完重定义操作后,所有的关联对象的名称都与原来不一样了。
再看看10g使用REGISTER_DEPENDENT_OBJECT的例子,执行完在线重定义,新生成的表对应的这些对象的名称是否能与原表一致:
SQL> SELECT * FROM V$VERSION;
BANNER
----------------------------------------------------------------
Oracle Database10gEnterprise Edition Release10.2.0.1.0 - Prod
PL/SQL Release 10.2.0.1.0 - Production
CORE 10.2.0.1.0 Production
TNS for 32-bit Windows: Version 10.2.0.1.0 - Production
NLSRTL Version 10.2.0.1.0 - Production
SQL> CREATE TABLE T AS SELECT ROWNUM ID, A.* FROM USER_OBJECTS A;
表已创建。
SQL> ALTER TABLE T ADD CONSTRAINT PK_T PRIMARY KEY (ID);
表已更改。
SQL> ALTER TABLE T ADD CHECK (ID > 0);
表已更改。
SQL> CREATE INDEX IND_T_NAME ON T (OBJECT_NAME);
索引已创建。
SQL> CREATE OR REPLACE TRIGGER TRI_T
2 BEFORE INSERT ON T
3 FOR EACH ROW
4 BEGIN
5 NULL;
6 END;
7 /
触发器已创建
SQL> CREATE TABLE T_INTER
2 PARTITION BY HASH (ID)
3 PARTITIONS 4
4 AS SELECT ROWNUM ID, A.*
5 FROM USER_OBJECTS A
6 WHERE 1 = 2;
表已创建。
SQL> ALTER TABLE T_INTER ADD CONSTRAINT PK_T_INTER PRIMARY KEY (ID);
表已更改。
SQL> ALTER TABLE T_INTER ADD CHECK (ID > 0) DISABLE;
表已更改。
SQL> CREATE INDEX IND_T_INTER_NAME ON T_INTER (OBJECT_NAME);
索引已创建。
SQL> CREATE OR REPLACE TRIGGER TRI_T_INTER
2 BEFORE INSERT ON T_INTER
3 FOR EACH ROW
4 BEGIN
5 NULL;
6 END;
7 /
触发器已创建
SQL> SET SERVEROUT ON SIZE 1000000
SQL> EXEC DBMS_REDEFINITION.CAN_REDEF_TABLE(USER, 'T')
PL/SQL过程已成功完成。
SQL> EXEC DBMS_REDEFINITION.START_REDEF_TABLE(USER, 'T', 'T_INTER')
PL/SQL过程已成功完成。
SQL> SELECT TABLE_NAME, INDEX_NAME
2 FROM USER_INDEXES
3 WHERE TABLE_NAME IN ('T', 'T_INTER');
TABLE_NAME INDEX_NAME
------------------------------ ------------------------------
T_INTER PK_T_INTER
T_INTER IND_T_INTER_NAME
T PK_T
T IND_T_NAME
SQL> SELECT TABLE_NAME, CONSTRAINT_NAME
2 FROM USER_CONSTRAINTS
3 WHERE TABLE_NAME IN ('T', 'T_INTER');
TABLE_NAME CONSTRAINT_NAME
------------------------------ ------------------------------
T PK_T
T SYS_C0011923
T_INTER PK_T_INTER
T_INTER SYS_C0011925
SQL> SELECT TABLE_NAME, TRIGGER_NAME
2 FROM USER_TRIGGERS
3 WHERE TABLE_NAME IN ('T', 'T_INTER');
TABLE_NAME TRIGGER_NAME
------------------------------ ------------------------------
T_INTER TRI_T_INTER
T TRI_T
SQL> BEGIN
2 DBMS_REDEFINITION.REGISTER_DEPENDENT_OBJECT(USER, 'T', 'T_INTER',
3 DBMS_REDEFINITION.CONS_INDEX, USER, 'IND_T_NAME', 'IND_T_INTER_NAME');
4 END;
5 /
PL/SQL过程已成功完成。
SQL> BEGIN
2 DBMS_REDEFINITION.REGISTER_DEPENDENT_OBJECT(USER, 'T', 'T_INTER',
3 DBMS_REDEFINITION.CONS_INDEX, USER, 'PK_T', 'PK_T_INTER');
4 END;
5 /
PL/SQL过程已成功完成。
SQL> BEGIN
2 DBMS_REDEFINITION.REGISTER_DEPENDENT_OBJECT(USER, 'T', 'T_INTER',
3 DBMS_REDEFINITION.CONS_CONSTRAINT, USER, 'SYS_C0011923', 'SYS_C0011925');
4 END;
5 /
PL/SQL过程已成功完成。
SQL> BEGIN
2 DBMS_REDEFINITION.REGISTER_DEPENDENT_OBJECT(USER, 'T', 'T_INTER',
3 DBMS_REDEFINITION.CONS_TRIGGER, USER, 'TRI_T', 'TRI_T_INTER');
4 END;
5 /
PL/SQL过程已成功完成。
SQL> EXEC DBMS_REDEFINITION.FINISH_REDEF_TABLE(USER, 'T', 'T_INTER')
PL/SQL过程已成功完成。
在线重定义操作已经完成,再次检查表上的索引、约束和触发器的名称:
SQL> SELECT TABLE_NAME, INDEX_NAME
2 FROM USER_INDEXES
3 WHERE TABLE_NAME IN ('T', 'T_INTER');
TABLE_NAME INDEX_NAME
------------------------------ ------------------------------
T PK_T
T IND_T_NAME
T_INTER PK_T_INTER
T_INTER IND_T_INTER_NAME
SQL> SELECT TABLE_NAME, CONSTRAINT_NAME
2 FROM USER_CONSTRAINTS
3 WHERE TABLE_NAME IN ('T', 'T_INTER');
TABLE_NAME CONSTRAINT_NAME
------------------------------ ------------------------------
T PK_T_INTER
T SYS_C0011923
T_INTER PK_T
T_INTER SYS_C0011925
SQL> SELECT TABLE_NAME, TRIGGER_NAME
2 FROM USER_TRIGGERS
3 WHERE TABLE_NAME IN ('T', 'T_INTER');
TABLE_NAME TRIGGER_NAME
------------------------------ ------------------------------
T TRI_T
T_INTER TRI_T_INTER
SQL> DROP TABLE T_INTER PURGE;
表已删除。
可以看到,如果时手工添加关联对象,也可以利用REGISTER_DEPENDENT_OBJECT过程来实现重定义后关联对象的重命名。实际上,如果使用COPY_TABLE_DEPENDENTS过程,Oracle会自动为所有的关联对象执行REGISTER_DEPENDENT_OBJECT过程。
两种方法都能实现同样的功能,而且也是各有各的优缺点。COPY_TABLE_DEPENDENTS过程更加方便,不容易出现遗漏。比如在这个例子中,执行REGISTER_DEPENDENT_OBJECT过程是就只注册了主键的索引,而没有注册主键的约束。因此最后主键对应的索引名称没有改变,而主键对应的约束名称则发生了变化。
而REGISTER_DEPENDENT_OBJECT过程最大的优势就是所有的操作自主权完全在用户手中,可以选择根据需要对指定的对象执行注册,具有很强的定制性。Oracle还提供了UNREGISTER_DEPENDENT_OBJECT过程来取消对象的注册。
oracle视频教程请关注:http://u.youku.com/user_video/id_UMzAzMjkxMjE2.html