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/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- Hive 日期處理Hive
- JSP 日期處理概述JS
- java localdate日期格式處理JavaLDA
- 日期時間處理包 Carbon
- Oracle SQL處理OracleSQL
- ORACLE 11G DATAGUARD 日誌中斷處理方案Oracle
- 關於Python中的日期處理Python
- Pandas中時間和日期處理
- sql server對於日期的處理SQLServer
- Laravel日期時間處理包 CarbonLaravel
- JDBC中Date日期物件的處理JDBC物件
- 字串和日期時間的處理字串
- Oracle審計--AUD$佔用空間較大處理方案Oracle
- Oracle壞塊處理Oracle
- oracle異常處理Oracle
- 分散式事務處理方案,微服事務處理方案分散式
- LocalDateTime替代Date操作處理日期時間LDA
- Java 8的18個常用日期處理Java
- oracle 高水位分析處理Oracle
- oracle高水位線處理Oracle
- oracle ORA-08104處理Oracle
- Oracle更新Opatch故障處理Oracle
- Oracle TX鎖的處理Oracle
- Clickhouse SQL日期處理函式及案例分享SQL函式
- Java SimpleDateFormat處理日期與字串的轉換JavaORM字串
- 一個日期處理類庫moment.jsJS
- 【Java】全域性日期處理,包含LocalDate, LocalDateTime, DateJavaLDA
- MySQL-日期和資料處理函式MySql函式
- LocalDate,LocalDateTime和處理時間、日期工具類LDA
- Oracle密碼過期處理Oracle密碼
- Oracle異常錯誤處理Oracle
- ORACLE 異常錯誤處理Oracle
- Oracle 監聽異常處理Oracle
- 【SQL】Oracle SQL處理的流程SQLOracle
- [工具]PHP 中的日期時間處理利器 – CarbonPHP
- java日期時間各種變換及處理Java
- Java入門教程五(數字和日期處理)Java
- laravel 使用maatwebsite/Excel 獲取的日期的處理LaravelWebExcel