Oracle Database將普通錶轉換為分割槽表遇到的問題
這篇文章討論一下在Oracle Database資料庫中將普通錶轉換為分割槽表過程中遇到的問題,這裡將普通錶轉換為分割槽表並沒有使用線上重定義的方法,使用最傳統的方法,將原始表重新命名,建立新表,把原始表中的資料INSERT到新表中,完成分割槽表的轉換。
線上重定義表的內容可參考文章《使用DBMS_REDEFINITION包執行線上重定義表》:http://blog.itpub.net/23135684/viewspace-1765128/
使用線上重定義將普通錶轉換為分割槽表的例子可參考文章《使用DBMS_REDEFINITION線上重定義表普通表為分割槽表》:http://blog.itpub.net/23135684/viewspace-661756/
下面透過測試進行說明:
C:\Users\LIUBINGLIN>sqlplus / as sysdba
SQL*Plus: Release 11.2.0.3.0 Production on 星期一 7月 27 12:42:54 2015
Copyright (c) 1982, 2011, Oracle. All rights reserved.
連線到:
Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 - Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options
SQL> select * from v$version where rownum<=2;
BANNER
--------------------------------------------------------------------------------
Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 - Production
PL/SQL Release 11.2.0.3.0 - Production
SQL> create user test1 identified by test1 default tablespace users temporary tablespace temp;
使用者已建立。
SQL> create user test2 identified by test2 default tablespace users temporary tablespace temp;
使用者已建立。
SQL> grant connect,resource to test1;
授權成功。
SQL> grant connect,resource to test2;
授權成功。
SQL> grant create view ,create trigger to test1;
授權成功。
SQL> grant create view ,create trigger to test2;
授權成功。
SQL> connect test1/test1
已連線。
SQL> show user
USER 為 "TEST1"
SQL> create table abc(id number,insdate date,name varchar2(20),age number); <<<< 建立一張測試表。
表已建立。
SQL> alter table abc add constraint pk_id primary key(id); <<<< 為表指定一個主鍵,主鍵會對應一個唯一索引。
表已更改。
SQL> create index ins_idx01 on abc(insdate); <<<< 建立一個普通索引。
索引已建立。
SQL> create view v_abc as select * from abc; <<<< 建立一個和測試表相關的檢視。
檢視已建立。
SQL> create table abc_mirror(id number,insdate date,name varchar2(20),age number); <<<< 建立一個測試表的觸發器。
表已建立。
SQL> create or replace trigger abc_trigger
2 after insert on test1.abc
3 for each row
4 begin
5 insert into test1.abc_mirror
6 values
7 (:new.id, :new.insdate, :new.name, :new.age);
8 commit;
9 end abc_trigger;
10 /
觸發器已建立
SQL> select * from abc;
未選定行
SQL> insert into abc values(1,sysdate,'a',12);
insert into abc values(1,sysdate,'a',12)
*
第 1 行出現錯誤:
ORA-04092: COMMIT 不能在觸發器中
ORA-06512: 在 "TEST1.ABC_TRIGGER", line 5
ORA-04088: 觸發器 'TEST1.ABC_TRIGGER' 執行過程中出錯
<<<< 從這個錯誤可以說明兩點,觸發器中不能包含COMMIT關鍵字,對測試表的事務和觸發器的事務是同一個事務,結束源表的事務即結束了觸發器中的事務。第二點是,如果觸發器出現問題,那麼對基礎表的操作不能正常進行。
SQL> create or replace trigger abc_trigger
2 after insert on abc
3 for each row
4 begin
5 insert into abc_mirror
6 values
7 (:new.id, :new.insdate, :new.name, :new.age);
8 end abc_trigger;
9 /
觸發器已建立
SQL> insert into abc values(1,sysdate,'a',12);
已建立 1 行。
SQL> commit; <<<< 觸發器中的事務也結束。
<<<< 這點以前有過文章說明:《儲存過程、觸發器與事務之間的關係》:http://blog.itpub.net/23135684/viewspace-709920/
提交完成。
SQL> select * from abc;
ID INSDATE NAME AGE
---------- -------------- -------------------- ----------
1 27-7月 -15 a 12
SQL> select * from abc_mirror;
ID INSDATE NAME AGE
---------- -------------- -------------------- ----------
1 27-7月 -15 a 12
SQL> select * from v_abc;
ID INSDATE NAME AGE
---------- -------------- -------------------- ----------
1 27-7月 -15 a 12
SQL> set linesize 200
SQL> select index_name,index_type,table_name from user_indexes where table_name='ABC'; <<<< 測試表有2個相關的索引。
INDEX_NAME INDEX_TYPE TABLE_NAME
------------------------------ --------------------------- ------------------------------
INS_IDX01 NORMAL ABC
PK_ID NORMAL ABC
SQL> select trigger_name,table_name from user_triggers where table_name='ABC'; <<<< 測試表有1個相關的觸發器。
TRIGGER_NAME TABLE_NAME
------------------------------ ------------------------------
ABC_TRIGGER ABC
SQL> grant select on abc to test2;
授權成功。
SQL> connect test2/test2
已連線。
SQL> show user
USER 為 "TEST2"
SQL> create view v_abc2 as select * from test1.abc;
檢視已建立。
SQL> connect test1/test1
已連線。
SQL> show user
USER 為 "TEST1"
SQL> alter table test1.abc rename to test1.abcd; <<<< 對錶進行重新命名操作,to後面的表名不能加上使用者的字首。
alter table test1.abc rename to test1.abcd
*
第 1 行出現錯誤:
ORA-14047: ALTER TABLE|INDEX RENAME 不能與其他分割槽組合
SQL> alter table test1.abc rename to abcd;
表已更改。
SQL> set linesize 200
SQL> select index_name,index_type,table_name,status from user_indexes where table_name='ABCD'; <<<< 對錶進行了重新命名,相關的索引會跟著發生變化,且狀態為VALID。
INDEX_NAME INDEX_TYPE TABLE_NAME STATUS
------------------------------ --------------------------- ------------------------------ --------
INS_IDX01 NORMAL ABCD VALID
PK_ID NORMAL ABCD VALID
SQL> select trigger_name,table_name,status from user_triggers where table_name='ABCD'; <<<< 對錶進行了重新命名,相關的觸發器會跟著發生變化,狀態為ENABLED,下面的測試結果也證明狀態是可用。這以為了在該觸發器中的程式碼會將原來的ABC自動的修改為ABCD。
TRIGGER_NAME TABLE_NAME STATUS
------------------------------ ------------------------------ --------
ABC_TRIGGER ABCD ENABLED
SQL> select * from abcd;
ID INSDATE NAME AGE
---------- -------------- -------------------- ----------
1 27-7月 -15 a 12
SQL> select * from abc_mirror;
ID INSDATE NAME AGE
---------- -------------- -------------------- ----------
1 27-7月 -15 a 12
SQL> select * from v_abc; <<<< 雖然觸發器會跟著變,但是檢視不會跟著變。
select * from v_abc
*
第 1 行出現錯誤:
ORA-04063: view "TEST1.V_ABC" 有錯誤
SQL> insert into abcd values(2,sysdate,'b',14);
已建立 1 行。
SQL> commit;
提交完成。
SQL> select * from abc_mirror;
ID INSDATE NAME AGE
---------- -------------- -------------------- ----------
2 27-7月 -15 b 14
1 27-7月 -15 a 12
SQL> connect test2/test2
已連線。
SQL> select * from v_abc2; <<<< 其他使用者,和測試表相關的檢視也不會跟著變。
select * from v_abc2
*
第 1 行出現錯誤:
ORA-04063: view "TEST2.V_ABC2" 有錯誤
除了以上的內容外,我們還可能想知道哪些資料庫物件關聯了某張表,或者某個資料庫物件引用了哪些表等等,這裡討論一下和此相關的3個資料字典:
>public_dependency PUBLIC_DEPENDENCY lists dependencies to and from objects, by object number.
>DBA_dependencies|ALL_dependencies|USER_dependencies DBA_DEPENDENCIES describes all dependencies in the database between procedures, packages, functions, package bodies, and triggers, including dependencies on views created without any database links.
>DBA_SOURCE|ALL_SOURCE|USER_SOURCE USER_SOURCE describes the text source of the stored objects owned by the current user.
下面的SQL語句可以查詢出哪些資料庫物件關聯了指定的表:
Select owner, object_type, object_name, object_id, status
from sys.DBA_OBJECTS
where object_id in
(Select object_id
from public_dependency
connect by prior object_id = referenced_object_id
start with referenced_object_id = (Select object_id
from sys.DBA_OBJECTS
where owner = 'TEST1' -- Owner
and object_name = 'ABCD' -- table_name
/*and object_type = :type*/ -- TABLE / SYNONYM
))
下面的SQL語句可以查詢出某個資料庫物件引用了哪些表:
select de.referenced_name
from user_dependencies de
where de.name = 'ABC_TRIGGER'
and de.referenced_type = 'TABLE';
下面的SQL語句可以查詢出某個資料庫物件引用了哪些序列:
select de.referenced_name
from user_dependencies de
where de.name = 'ABC_TRIGGER'
and de.referenced_type = 'SEQUENCE';
以上的測試結果在分割槽錶轉換的情況下會出現以下的問題:
1).由於觸發器會跟著表名的變化而自動的調整程式碼,這在新分割槽表插入資料之後需要重新修改編譯相應的所有觸發器,將其調整回原來的表名,這個可以透過USER_TRIGGER.TABLE_NAME欄位來確定相關的觸發器。
2).由於檢視、儲存過程(沒有USER_PROCESSES.TABLE_NAME資料字典)等不會發生變化,所以需要手動的驗證相關的物件是否可用。
3).為了不影響表相關物件的正常使用,在調整完成後應該執行utlrp.sql指令碼,手動重新編譯一下不正確的物件,確保表相關的物件都能夠正常的使用,特別是觸發器,觸發器變得無效會使和源表相關的所有事務都無法執行。
4).另外,新的分割槽表建議重新收集一下表的統計資訊。
5).在建立分割槽表的時候,除了注意表本身外,還需要注意建立表的索引,主外來鍵,各種約束,授權等(這個可以透過PL/SQL工具在檢視錶的原始碼時很好的展現出來)。
6).為了提高將舊錶資料插入分割槽表的速度,建議先插入資料到分割槽表,最後來建立索引,主外來鍵,各種約束和建立授權,在將舊錶插入分割槽表時可以酌情考慮指定/*+APPEND PARALLEL(4) NOLOGGING*/的提示來提高資料的插入效率。
--end--
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/23135684/viewspace-1753024/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- Oracle 將普通錶轉換為分割槽表Oracle
- 將普通錶轉換為分割槽表
- 普通錶轉換為分割槽表
- 【分割槽】如何將一個普通錶轉換為分割槽表
- ORACLE將普通錶轉變為分割槽表方法Oracle
- Oracle線上將普通錶轉分割槽表Oracle
- 利用線上重定義功能將普通錶轉換為分割槽表問題
- 將非分割槽錶轉換為分割槽表
- ORACLE普通錶轉換成分割槽表的操作Oracle
- 將mysql非分割槽錶轉換為分割槽表MySql
- 將一個非分割槽錶轉換為分割槽表
- ORACLE 普通錶轉換成分割槽表(線上重定義)Oracle
- 批次轉換分割槽表為普通表
- 批量轉換分割槽表為普通表
- 【ASK_ORACLE】使用insert語句將普通錶轉換成分割槽表Oracle
- 普通錶轉換分割槽表-線上重定義
- 普通錶轉換成分割槽表的四種方法
- ORACLE 普通錶轉換成分割槽表(線上重定義)(zt)Oracle
- 線上表格重定義研究,比如將普通錶轉換為分割槽表等
- 線上重定義 ?普通錶轉換成分割槽表
- 非分割槽錶轉換為分割槽表和partition indexIndex
- 非分割槽錶轉換成分割槽表
- MySQL普通錶轉換成分割槽表的兩種方法舉例MySql
- ORACLE 11g 範圍分割槽錶轉換INTERVAL分割槽表Oracle
- 高手幫忙,超大普通錶轉分割槽表?
- 堆錶轉換成分割槽表
- Oracle普通表修改為分割槽表的方法Oracle
- 線上重定義的操作步驟__普通錶轉換為分割槽表的實驗案例
- 使用ORACLE線上重定義將普通表改為分割槽表Oracle
- LightDB 22.4 新特性之相容Oracle線上轉換普通表為分割槽表Oracle
- 非分割槽錶轉換成分割槽表以及注意事項
- Oracle 12C新特性-線上把非分割槽錶轉為分割槽表Oracle
- oracle將表配置為分割槽表Oracle
- oracle9i 普通表改為分割槽表Oracle
- oracle 普通表-分割槽表改造流程Oracle
- Oracle 12.2之後ALTER TABLE .. MODIFY轉換非分割槽表為分割槽表Oracle
- ORACLE將不同表改為分割槽表Oracle
- 使用dbms_redefinition包線上把大資料量非分割槽錶轉換為分割槽表大資料