Oracle非法日期 處理方案
說明
該文件用於解決同步中出現非法日期的報錯。
現象說明
在同步時,發現在應用端經常會出現非法日期的報錯,類似於月份無效等。因為 oracle 對 date 型別是會做檢查的,當不在指定的範圍內時,就會報錯,最終導致同步異常。而在源端能將這種非法的日期插入,是因為在應用端做過處理,所以非法日期能進入資料庫而不報錯,但是在資料庫中查到的日期都是 0000-00-00 。
方案
l 規範應用
l 目標端date型別改為char型,透過OGG做轉換後同步(前提是客戶接受欄位型別改變)
解決方案模擬
下面將模擬透過方案二解決報錯的過程(資料同步軟體已經安裝)
建立測試表
建立測試表 test ,插入部分資料
SQL> create table test (id number,name varchar2(100),birthday date);
Table created.
SQL> insert into test values (1,'ALICE',to_date('1991-01-01','yyyy-mm-dd'));
1 row created.
SQL> insert into test values (2,'BOB',to_date('1960-11-21','yyyy-mm-dd'));
1 row created.
SQL> insert into test values (3,'SUNNY',to_date('1989-09-03','yyyy-mm-dd'));
1 row created.
SQL> commit;
Commit complete.
select * from test;
ID NAME BIRTHDAY
---------- -------------------- ------------
1 ALICE 01-JAN-91
2 BOB 21-NOV-60
3 SUNNY 03-SEP-89
同步test 表
初始化 test 表到目標端,並將 test 表加到資料同步軟體中(過程略)
檢視目標端資料庫
SQL> select * from test;
ID NAME BIRTHDAY
---------- -------------------- ------------
1 ALICE 01-JAN-91
2 BOB 21-NOV-60
3 SUNNY 03-SEP-89
測試合法時間插入
源端插入正常的時間
SQL> insert into test values (4,'SONIA',to_date('1997-04-14','yyyy-mm-dd'));
1 row created.
SQL> commit;
Commit complete.
SQL> select * from test;
ID NAME BIRTHDAY
---------- -------------------- ------------
1 ALICE 01-JAN-91
2 BOB 21-NOV-60
3 SUNNY 03-SEP-89
4 SONIA 14-APR-97
目標端檢視:
SQL> select * from test;
ID NAME BIRTHDAY
---------- -------------------- ---------
4 SONIA 14-APR-97
1 ALICE 01-JAN-91
2 BOB 21-NOV-60
3 SUNNY 03-SEP-89
資料可以正常同步。
測試非法時間插入
源端插入非法日期
SQL> insert into test values (5,'PAIGE',to_date('0001-01-01','yyyy-mm-dd')-1);
1 row created.
SQL> commit;
Commit complete.
select id,name,to_char(BIRTHDAY,'yyyy-mm-dd') from test;
ID NAME TO_CHAR(BI
---------- -------------------- ----------
1 ALICE 1991-01-01
2 BOB 1960-11-21
3 SUNNY 1989-09-03
4 SONIA 1997-04-14
5 PAIGE 0000-00-00 # 非法日期
目標端發現沒有新插入的非法日期這條記錄
檢視同步軟體日誌,發現報錯如下:
[oracle@slave odc]$ tail -f ggserr.log
2017-11-09 06:06:52 INFO OGG-00996 Oracle GoldenGate Delivery for Oracle, sm_rep.prm: REPLICAT SM_REP started.
2017-11-09 06:06:52 WARNING OGG-00869 Oracle GoldenGate Delivery for Oracle, sm_rep.prm: No unique key is defined for table 'TEST'. All viable columns will be used to represent the key, but may not guarantee uniqueness. KEYCOLS may be used to define the key.
2017-11-09 06:13:55 WARNING OGG-00869 Oracle GoldenGate Delivery for Oracle, sm_rep.prm: No unique key is defined for table 'T2'. All viable columns will be used to represent the key, but may not guarantee uniqueness. KEYCOLS may be used to define the key.
2017-11-09 06:25:07 WARNING OGG-00869 Oracle GoldenGate Delivery for Oracle, sm_rep.prm: OCI Error ORA-01841: ( 完整 ) 年份值必須介於 -4713 和 +9999 之間 , 且不為 0 (status = 1841). INSERT /*+ RESTRICT_ALL_REF_CONS */ INTO "ZMY"."TEST" ("ID","NAME","BIRTHDAY") VALUES (:a0,:a1,:a2).
2017-11-09 06:25:07 WARNING OGG-01004 Oracle GoldenGate Delivery for Oracle, sm_rep.prm: Aborted grouped transaction on 'ZMY.TEST', Database error 1841 (OCI Error ORA-01841: ( 完整) 年份值必須介於 -4713 和 +9999 之間, 且不為 0 (status = 1841). INSERT /*+ RESTRICT_ALL_REF_CONS */ INTO "ZMY"."TEST" ("ID","NAME","BIRTHDAY") VALUES (:a0,:a1,:a2)).
2017-11-09 06:25:07 WARNING OGG-01003 Oracle GoldenGate Delivery for Oracle, sm_rep.prm: Repositioning to rba 1490 in seqno 2.
2017-11-09 06:25:07 WARNING OGG-01154 Oracle GoldenGate Delivery for Oracle, sm_rep.prm: SQL error 1841 mapping ZMY.TEST to ZMY.TEST OCI Error ORA-01841: ( 完整) 年份值必須介於 -4713 和 +9999 之間, 且不為 0 (status = 1841). INSERT /*+ RESTRICT_ALL_REF_CONS */ INTO "ZMY"."TEST" ("ID","NAME","BIRTHDAY") VALUES (:a0,:a1,:a2).
2017-11-09 06:25:07 WARNING OGG-01003 Oracle GoldenGate Delivery for Oracle, sm_rep.prm: Repositioning to rba 1490 in seqno 2.
2017-11-09 06:25:07 ERROR OGG-01296 Oracle GoldenGate Delivery for Oracle, sm_rep.prm: Error mapping from ZMY.TEST to ZMY.TEST.
2017-11-09 06:25:07 ERROR OGG-01668 Oracle GoldenGate Delivery for Oracle, sm_rep.prm: PROCESS ABENDING.
日誌顯示年份不在規定範圍內,無法插入資料庫。
修改備端欄位型別
增加一個臨時列,型別為需要的 varchar2
SQL> alter table test add date_temp varchar2(100);
Table altered.
SQL> commit;
Commit complete.
SQL> select * from test;
ID NAME BIRTHDAY DATE_TEMP
---------- -------------------- ------------------- -------------------------------
4 SONIA 14-APR-97
1 ALICE 01-JAN-91
2 BOB 21-NOV-60
3 SUNNY 03-SEP-89
Rename 原欄位
SQL> alter table test rename column birthday to birthday_bak;
Table altered.
SQL> select * from test;
ID NAME BIRTHDAY_BAK DATE_TEMP
---------- -------------------- ---------------------------------------- ------------------------------
4 SONIA 14-APR-97
1 ALICE 01-JAN-91
2 BOB 21-NOV-60
3 SUNNY 03-SEP-89
SQL> desc test;
Name Null? Type
----------------------------------------- -------- ----------------------------
ID NUMBER
NAME VARCHAR2(100)
BIRTHDAY_BAK DATE
DATE_TEMP VARCHAR2(100)
將原列上的資料更新到新加的臨時列
SQL> update test set date_temp = cast(birthday_bak as varchar2(100));
4 rows updated.
SQL> commit;
Commit complete.
SQL> select * from test;
ID NAME BIRTHDAY_BAK DATE_TEMP
---------- -------------------- ---------------------------------------- ------------------------------
4 SONIA 14-APR-97 14-APR-97
1 ALICE 01-JAN-91 01-JAN-91
2 BOB 21-NOV-60 21-NOV-60
3 SUNNY 03-SEP-89 03-SEP-89
刪除原列
SQL> alter table test drop column birthday_bak;
Table altered.
SQL> commit;
Commit complete.
SQL> select * from test;
ID NAME DATE_TEMP
---------- -------------------- ------------------------------
4 SONIA 14-APR-97
1 ALICE 01-JAN-91
2 BOB 21-NOV-60
3 SUNNY 03-SEP-89
修改新增列為原列名稱
SQL> alter table test rename column date_temp to birthday;
SQL> commit;
Commit complete.
SQL> desc test;
Name Null? Type
----------------------------------------- -------- ----------------------------
ID NUMBER
NAME VARCHAR2(100)
BIRTHDAY VARCHAR2(100)
源端同步軟體生成定義檔案
編輯
GGSCI (rac2) 3> edit params defgen
defsfile /odc/dirdef/sm.def purge
userid odc, password odc
table zmy.t2;
table zmy.test;
desfile : def 檔案輸出路徑
table: 可以指定 table ,也可以使用 account.* 到處相應賬戶下所有表結構資訊。
生成目標端需要的定義檔案
[oracle@rac2 ~]$ cd /odc
[oracle@rac2 odc]$ ./defgen paramfile /odc/dirprm/defgen.prm
會在 /odc/dirdef 路徑下生成 sm.def 檔案。
並將產生的定義檔案傳輸到目標端的 dirdef 目錄下
修改目標端應用程式
編輯對應的應用程式引數檔案
新增引數 SOURCEDEFS
GGSCI (slave) 2> view param sm_rep
replicat sm_rep
setenv (NLS_LANG="SIMPLIFIED CHINESE_CHINA.ZHS16GBK")
userid odc, password odcASSUMETARGETDEFS
ALLOWNOOPUPDATES
SOURCEDEFS /odc/dirdef/sm.def
DBOPTIONS DEFERREFCONST
--batchsql
ddlerror 955 ignore
ddlerror 1917 ignore
ddlerror 24344 ignore
ddl include mapped
DISCARDFILE ./dirrpt/sm.dsc, APPEND megabytes 20
DISCARDROLLOVER on sunday
map zmy.test,target zmy.test;
修改後啟動程式
GGSCI (slave) 3> start am_rep
GGSCI (slave) 4> info all
MANAGER RUNNING
REPLICAT RUNNING SM_REP 00:00:00 00:00:00
程式正常同步
檢查目標端測試表
檢視到資料正常插入
SQL> select * from test;
ID NAME BIRTHDAY
---------- -------------------- -------------------------------------------------------------------------
4 SONIA 14-APR-97
1 ALICE 01-JAN-91
2 BOB 21-NOV-60
3 SUNNY 03-SEP-89
5 PAIGE 0000-12-31:00:00:00
總結
透過該方法,同步軟體可以正常同步資料,目標庫也能插入非法日期,不過查到的日期和生產一樣是一個損壞的日期。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/31547506/viewspace-2926358/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 在oracle中處理日期Oracle
- oracle日期處理集錦Oracle
- MySQL 處理非法資料薦MySql
- Scala日期處理
- JavaUtils - 日期處理Java
- java(日期處理)Java
- jstl處理日期JS
- 在Oracle中實現各種日期處理(1)Oracle
- 在Oracle中實現各種日期處理(2)Oracle
- JSP 日期處理概述JS
- java localdate日期格式處理JavaLDA
- Oracle 中的 TO_DATE 和 TO_CHAR 函式 日期處理Oracle函式
- Pandas中時間和日期處理
- 日期時間處理包 Carbon
- sql server對於日期的處理SQLServer
- 字串和日期時間的處理字串
- JDBC中Date日期物件的處理JDBC物件
- Laravel日期時間處理包 CarbonLaravel
- 幾個SQL 日期處理函式SQL函式
- 分散式事務處理方案,微服事務處理方案分散式
- 關於Python中的日期處理Python
- Java 8的18個常用日期處理Java
- joda jar日期處理類的學習JAR
- lubridate—輕鬆處理日期時間
- js日期物件相容性的處理JS物件
- ORACLE 11G DATAGUARD 日誌中斷處理方案Oracle
- 資料庫timesten與 oracle 處理日期上寫法上的不同資料庫Oracle
- 水庫斷面水位中--水勢顯示效果處理--日期處理 SQLSQL
- Java SimpleDateFormat處理日期與字串的轉換JavaORM字串
- MySQL-日期和資料處理函式MySql函式
- 日期和時間的儲存與處理
- 【Util】java處理日期時間相加減大全Java
- Oracle審計--AUD$佔用空間較大處理方案Oracle
- Oracle SQL處理OracleSQL
- [工具]PHP 中的日期時間處理利器 – CarbonPHP
- Java入門教程五(數字和日期處理)Java
- laravel 使用maatwebsite/Excel 獲取的日期的處理LaravelWebExcel
- LocalDate,LocalDateTime和處理時間、日期工具類LDA