2017-07-25 89 views
0

在continuned我last post - 「遷移甲骨文到PostgreSQL無效字節序列編碼‘UTF8’:0×00」的PostgreSQL 9.5 - 解碼/選擇的情況下解決與UTF8行不通的錯誤

我試着插入到本地來自遠程oracle表的postgresql表數據(通過oracle_fdw擴展)。我的oracle表有一個名爲street的列,它有有效的字符串值,有時下一個無效的(在postgresql中)字符串:''(空格)。當我嘗試複製列值時,出現上面提到的錯誤以及我上一篇文章中提到的錯誤。我知道我需要在將其插入到postgresql之前更改oracle數據。我必須在飛行中這樣做,所以我試圖在postgresql中搜索oracle解碼函數。我發現2解決方案,我用他們兩個,但我得到了同樣的錯誤:

mydb=>select *,(case when v.street=' ' then null END) from customer_prod v; 
ERROR: invalid byte sequence for encoding "UTF8": 0x00 
CONTEXT: converting column "street" for foreign table scan of 
"customer_prod", row 254148 

2,使用解碼功能從orafce擴展:

mydb=>select decode(street,' ',null) from customer_prod; 
ERROR: invalid byte sequence for encoding "UTF8": 0x00 

1.使用有選擇的情況下

所以,我仍然得到錯誤。任何想法我怎麼能解決這個問題?

回答

3

將值從Oracle傳輸到PostgreSQL時發生錯誤,因此後處理不會阻止該錯誤。

出於演示的緣故,讓我們創建一個具有該問題的Oracle表:

CREATE TABLE nulltest(
    id number(5) CONSTRAINT nulltest_pkey PRIMARY KEY, 
    val varchar2(10 CHAR) 
); 

INSERT INTO nulltest VALUES (1, 'schön'); 
INSERT INTO nulltest VALUES (2, 'bö' || CHR(0) || 'se'); 
INSERT INTO nulltest VALUES (3, 'egal'); 

COMMIT; 

讓我們在PostgreSQL中創建一個外部表吧:

CREATE FOREIGN TABLE nulltest (
    id integer OPTIONS (key 'true') NOT NULL, 
    val varchar(10) 
) SERVER oracle 
    OPTIONS (table 'NULLTEST'); 

SELECT * FROM nulltest; 

ERROR: invalid byte sequence for encoding "UTF8": 0x00 
CONTEXT: converting column "val" for foreign table scan of "nulltest", row 2 

現在最簡單的事情是創建一個可以過濾掉零字符的外表:

CREATE FOREIGN TABLE filter_nulltest (
    id integer OPTIONS (key 'true') NOT NULL, 
    val varchar(10) 
) SERVER oracle 
    OPTIONS (table '(SELECT id, replace(val, CHR(0), NULL) FROM nulltest)'); 

SELECT * FROM filter_nulltest; 

┌────┬───────┐ 
│ id │ val │ 
├────┼───────┤ 
│ 1 │ schön │ 
│ 2 │ böse │ 
│ 3 │ egal │ 
└────┴───────┘ 
(3 rows) 

另一個效率較低的選項是創建一個捕獲並向您報告壞行的函數,以便您可以在Oracle端修復它們:

CREATE OR REPLACE FUNCTION get_nulltest() RETURNS SETOF nulltest 
    LANGUAGE plpgsql AS 
$$DECLARE 
    v_id integer; 
    n nulltest; 
BEGIN 
    FOR v_id IN SELECT id FROM nulltest 
    LOOP 
     BEGIN 
     SELECT nulltest.* INTO n 
      FROM nulltest 
      WHERE id = v_id; 
     RETURN NEXT n; 
     EXCEPTION 
     WHEN OTHERS THEN 
      RAISE NOTICE 'Caught error % for id=%: %', SQLSTATE, v_id, SQLERRM; 
     END; 
    END LOOP; 
END;$$; 

SELECT * FROM get_nulltest(); 

NOTICE: Caught error 22021 for id=2: invalid byte sequence for encoding "UTF8": 0x00 
┌────┬───────┐ 
│ id │ val │ 
├────┼───────┤ 
│ 1 │ schön │ 
│ 3 │ egal │ 
└────┴───────┘ 
(2 rows) 
+0

非常感謝Laurenz!你在最後的帖子中幫了我很多。你是最棒的 ! – Mariel

+0

確實CHR(0)=''(空格)?當我切換CHR(0)與''選擇工作,但如果我使用CHR(0)我得到錯誤:空字符不允許 – Mariel

+0

CHR(0)<>'''在Oracle中。在PostgreSQL中,你不能像解釋的那樣使用'CHR(0)'。 –