2017-07-25 90 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)'。 –