10g線上重定義新特性——關聯物件自動重新命名(二)

yangtingkun發表於2009-06-27

9i的線上重定義存在一個問題,執行完線上重定義後,表的名稱雖然保持不變,但是索引、約束、觸發器等關聯物件的名稱會發生變化,有時候這會帶來一定的問題,而要在事後手工修改,會比較麻煩。

10g的線上重定義解決這個問題。如果物件是利用COPY_TABLE_DEPENDENTS建立的,那麼這些關聯的物件在重定義操作完成後,自動改為原始的名稱。如果是手工建立的關聯物件,則可以利用REGISTER_DEPENDENT_OBJECT過程,所有執行了REGISTER_DEPENDENT_OBJECT過程的關聯物件,都會在重定義操作完成後自動重新命名。

這篇文章來看REGISTER_DEPENDENT_OBJECT的例子。

10g線上重定義新特性——關聯物件自動重新命名(一):http://yangtingkun.itpub.net/post/468/486498

 

 

上一篇介紹了10gCOPY_TABLE_DEPENDENTS的例子,這篇看看手工建立關聯物件,然後使用REGISTER_DEPENDENT_OBJECT的例子。

首先還是先看9i的例子:

SQL> SELECT * FROM V$VERSION;

BANNER
----------------------------------------------------------------
Oracle9i Enterprise Edition Release 9.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 Database 10g Enterprise Edition Release 10.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過程來取消物件的註冊。

 

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/4227/viewspace-607737/,如需轉載,請註明出處,否則將追究法律責任。

相關文章