在平時的工做中,有時候須要insert一批數據,這些數據多是臨時表,外部表,普通表,子查詢等形式,相似下面的格式
insert into xxxx (select xxxxx from xxx where xxxxx);
若是其中有冗餘數據的時候,整個Insert會自動rollback,一條數據也插不進去,錯誤相似下面的形式。
insert /*+ append */into mo1_memo select *from MO1_MEMO_EXT_92;
*
ERROR at line 1:
ORA-00001: unique constraint (MIG_TEST.MO1_MEMO_PK) violated
可能咱們想保證正常數據可以插入,對於違反約束等的數據稍後處理,這個是用錯誤日誌就是一個很好的選擇。
首先就是建立錯誤日誌,可使用提供的包來建立,也能夠手動建立。
這裏我須要用到表含有lob字段,建立錯誤日誌的時候有下面的錯誤。
EXEC DBMS_ERRLOG.create_error_log(dml_table_name => 'MO1_MEMO')
BEGIN DBMS_ERRLOG.create_error_log(dml_table_name => 'MO1_MEMO'); END;
ERROR at line 1:
ORA-20069: Unsupported column type(s) found: MEMO_SYSTEM_TEXT_C
ORA-06512: at "SYS.DBMS_ERRLOG", line 235
ORA-06512: at line 1
不過想一想也是合理的。不過問題仍是要解決的。
能夠看看建立錯誤日誌的包,Oracle已經考慮到了,咱們能夠忽略這種不支持的類型,固然還能夠指定錯誤日誌的名字。
SQL> desc dbms_errlog
PROCEDURE CREATE_ERROR_LOG
Argument Name Type In/Out Default?
------ --------
DML_TABLE_NAME VARCHAR2 IN
ERR_LOG_TABLE_NAME VARCHAR2 IN DEFAULT
ERR_LOG_TABLE_OWNER VARCHAR2 IN DEFAULT
ERR_LOG_TABLE_SPACE VARCHAR2 IN DEFAULT
SKIP_UNSUPPORTED BOOLEAN IN DEFAULT
咱們建立錯誤日誌
SQL> EXEC DBMS_ERRLOG.create_error_log(dml_table_name => 'MO1_MEMO',SKIP_UNSUPPORTED=>true,ERR_LOG_TABLE_NAME=>'MO1_MEMO_ERROR');
PL/SQL procedure successfully completed.
Elapsed: 00:00:00.03
嘗試插入有冗餘的數據,
SQL> insert /*+ append */into mo1_memo select *from MO1_MEMO_EXT_92 LOG ERRORS INTO MO1_MEMO_ERROR('test_unique') REJECT LIMIT UNLIMITED
2 /
insert /*+ append */into mo1_memo select *from MO1_MEMO_EXT_92 LOG ERRORS INTO MO1_MEMO_ERROR('test_unique') REJECT LIMIT UNLIMITED
*
ERROR at line 1:
ORA-00001: unique constraint (MIG_TEST.MO1_MEMO_PK) violated
Elapsed: 00:00:17.32
直接拋了錯誤,看來錯誤日誌沒有正確啓用。
查看錯誤日誌,裏面也是空的。
SQL> SELECT *FROM MO1_MEMO_ERROR; --no rows
反覆嘗試,最後發現是Hint的緣由,去掉Hint 就沒有問題了。
SQL> insert into mo1_memo select *from MO1_MEMO_EXT_92 LOG ERRORS INTO MO1_MEMO_ERROR('test_unique') REJECT LIMIT UNLIMITED;
99 rows created.
Elapsed: 00:04:04.83
1* select count(*)from mo1_memo_error
SQL> /
COUNT(*)
907544
錯誤日誌裏面有詳細的數據信息。可是若是足夠細心查看執行時間的話,就會發現若是不使用append,性能就會差不少。
下面是一個簡單的測試,
若是不使用append的時候,插入80萬左右的數據在1分鐘左右,若是使用了append就只須要大概13秒左右。
還有上面的測試結果,若是80萬記錄中99%左右的數據有冗餘,插入錯誤日誌就須要大概4分鐘的樣子
SQL> insert into mo1_memo select * from mo1_memo_ext_99 LOG ERRORS INTO MO1_MEMO_ERROR REJECT LIMIT UNLIMITED;
877245 rows created.
Elapsed: 00:01:12.91
SQL> insert into mo1_memo select * from mo1_memo_ext_98;
753637 rows created.
Elapsed: 00:01:04.75
SQL> rollback;
Rollback complete.
Elapsed: 00:00:56.35
SQL> insert /*+append*/ into mo1_memo select *from mo1_memo_ext_98;
753637 rows created.
Elapsed: 00:00:13.20
因此啓用錯誤日誌能夠根據你們的需求來選擇,有利有弊。app