DBMS_ERRLOG記錄DML錯誤日志(二)


   上一篇簡單介紹了DML記錄語句的限制,雖然所有的例子都是利用INSERT語句,但是LOG ERRORS語句並沒有這個限制,UPDATEDELETEMERGE都可以使用這個語句。下面要說的就是這篇的重點,LOG ERRORS語句的限制。

不支持的操作:

違反延遲約束;

直接路徑的INSERT或MERGE語句違反了唯一約束或唯一索引;

更新操作違反了唯一約束或唯一索引。

不支持的數據類型:

比如:LONG、LONG RAW、BLOG、CLOB、NCLOB、BFILE以及各種對象類型。Oracle不支持這些類型的原因也很簡單,這些特殊的類型不是包含了大量的記錄,就是需要通過特殊的方法來讀取,因此Oracle沒有辦法在SQL處理的時候將對應列的信息寫到錯誤記錄表中。

1.下面我們來看不支持的操作,首先看一下違反延遲約束,

SQL> ALTER TABLE T1 ADD CONSTRAINT PK_T1_B CHECK (B IS NOT NULL) DEFERRABLE INITIALLY DEFERRED;
Table altered

測試語句:

SQL> INSERT INTO T1 VALUES('21','') LOG ERRORS INTO ERR_T1('ERR_T1')REJECT LIMIT UNLIMITED;
1 row inserted
SQL> commit;
commit
ORA-02091: 事務處理已回退
ORA-02290: 違反檢查約束條件 (NREI.PK_T1_B)

    由於延遲約束的檢查在COMMIT時刻進行,而不是在DML發生的時刻,因此不會利用LOG ERRORS語句將違反結果的記錄插入到記錄表中,這也是很容易理解的。

下面看看直接路徑插入違反唯一約束的情況:

SQL> INSERT /*+ APPEND */ INTO T1 SELECT * FROM T2 LOG ERRORS INTO ERR_T1('ERR_T1')REJECT LIMIT UNLIMITED;
INSERT /*+ APPEND */ INTO T1 SELECT * FROM T2 LOG ERRORS INTO ERR_T1('ERR_T1')REJECT LIMIT UNLIMITED
ORA-00001: 違反唯一約束條件 (NREI.PK_T1_A)

直接路徑插入本身就很特殊,在執行過程中會繞過很多常規SQL執行的步驟,因此LOG ERRORS語句對其無效也是可以理解的。

最后來看看更新語句違反唯一約束的情況:

SQL> UPDATE T1 SET A='1' WHERE A='2' LOG ERRORS INTO ERR_T1('ERR_T1')REJECT LIMIT UNLIMITED;
UPDATE T1 SET A='1' WHERE A='2' LOG ERRORS INTO ERR_T1('ERR_T1')REJECT LIMIT UNLIMITED
ORA-00001: 違反唯一約束條件 (NREI.PK_T1_A)

    可以看到,如果更新操作導致了唯一約束或唯一索引沖突,也是不會記錄到錯誤記錄表中的。至於為什么更新操作會產生這種情況,還沒有想明白,不過主鍵的沖突和其他約束沖突有所區別,Oracle在處理的時候很可能會有所考慮。

2.下面我們來看不支持的數據類型

SQL> DROP TABLE ERR_T1 PURGE;
Table dropped

SQL> alter table T1 add c clob;

Table altered
SQL> EXEC DBMS_ERRLOG.CREATE_ERROR_LOG('T1','ERR_T1','NREI');
begin DBMS_ERRLOG.CREATE_ERROR_LOG('T1','ERR_T1','NREI'); end;
ORA-20069: Unsupported column type(s) found: C
ORA-06512: 在 "SYS.DBMS_ERRLOG", line 234
ORA-06512: 在 line 1

可以看到,由於T1表擁有不支持的列,導致創建錯誤記錄表的過程報錯,錯誤提示就是T1表中包含了不支持的列。

如果手工添加CLOB字段到錯誤記錄表:

SQL> alter table T1 DROP (c);
Table altered
SQL> EXEC DBMS_ERRLOG.CREATE_ERROR_LOG('T1','ERR_T1','NREI');
PL/SQL procedure successfully completed
SQL> alter table T1 add c clob;
Table altered
SQL> alter table ERR_T1 add c clob;
Table altered

執行插入語句:

SQL> INSERT INTO T1 VALUES('21','21','TEST') LOG ERRORS INTO ERR_T1('ERR_T1')REJECT LIMIT UNLIMITED;
INSERT INTO T1 VALUES('21','21','TEST') LOG ERRORS INTO ERR_T1('ERR_T1')REJECT LIMIT UNLIMITED
ORA-38904: LOB 列 "C" 不支持 DML 錯誤事件記錄

可以看到,Oracle會直接報錯。

SQL> UPDATE T1 SET A='22' WHERE A='2' LOG ERRORS INTO ERR_T1('ERR_T1')REJECT LIMIT UNLIMITED;
UPDATE T1 SET A='22' WHERE A='2' LOG ERRORS INTO ERR_T1('ERR_T1')REJECT LIMIT UNLIMITED
ORA-38904: LOB 列 "C" 不支持 DML 錯誤事件記錄

OracleDML並不包含不支持列的數據,Oracle也會報錯,說明Oracle是在執行之前檢查了錯誤記錄表的數據類型,而不是在執行的時候才去處理。

SQL> alter table ERR_T1 DROP (c);
Table altered
SQL> INSERT INTO T1 VALUES('1','1','TEST' ) LOG ERRORS INTO ERR_T1('ERR_T1')REJECT LIMIT UNLIMITED;
0 rows inserted

可以看到,刪除錯誤記錄語句所不支持的列后,LOG ERRORS語句反而可以順利執行,而且無論DML語句是否包括哪些不支持列的數據。






免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM