PostgreSQL 9.5 - 解码/选择大小写来解决 utf8 错误不起作用

Jey*_*eyJ 0 oracle postgresql utf-8 oracle-fdw

继续我的上一篇文章- “将 oracle 迁移到 postgresql 编码 \xe2\x80\x9cUTF8\xe2\x80\x9d 的字节序列无效:0x00”

\n

我正在尝试将远程 Oracle 表中的数据插入到本地 PostgreSQL 表中(通过 oracle_fdw 扩展)。我的 Oracle 表有一个名为 street 的列,它具有有效的字符串值,有时还有下一个无效(在 PostgreSQL 中)字符串:\' \'(空格)。

\n

当我尝试复制列值时,我收到上面和上一篇文章中提到的错误。我明白在将 oracle 数据插入到 PostgreSQL 之前我需要更改它。我必须即时执行此操作,因此我尝试在 PostgreSQL 中搜索 oracle 解码函数。我找到了两个解决方案,并且都使用了它们,但出现了相同的错误:

\n

1.使用带有大小写的选择:

\n
mydb=>select *,(case when v.street=\' \' then null END) from customer_prod v;\nERROR:  invalid byte sequence for encoding "UTF8": 0x00\nCONTEXT:  converting column "street" for foreign table scan of \n "customer_prod", row 254148\n
Run Code Online (Sandbox Code Playgroud)\n
\n

2.使用orafce扩展中的解码函数:

\n
mydb=>select decode(street,\' \',null) from customer_prod;\nERROR:  invalid byte sequence for encoding "UTF8": 0x00\n
Run Code Online (Sandbox Code Playgroud)\n

所以,我仍然收到错误。我该如何解决这个问题?

\n

Lau*_*lbe 5

当值从 Oracle 传输到 PostgreSQL 时会发生错误,因此后处理不会阻止该错误。

\n\n

为了演示,让我们创建一个显示该问题的 Oracle 表:

\n\n
CREATE TABLE nulltest(\n   id number(5) CONSTRAINT nulltest_pkey PRIMARY KEY,\n   val varchar2(10 CHAR)\n);\n\nINSERT INTO nulltest VALUES (1, \'sch\xc3\xb6n\');\nINSERT INTO nulltest VALUES (2, \'b\xc3\xb6\' || CHR(0) || \'se\');\nINSERT INTO nulltest VALUES (3, \'egal\');\n\nCOMMIT;\n
Run Code Online (Sandbox Code Playgroud)\n\n

让我们在 PostgreSQL 中为其创建一个外部表:

\n\n
CREATE FOREIGN TABLE nulltest (\n   id integer OPTIONS (key \'true\') NOT NULL,\n   val varchar(10)\n) SERVER oracle\n   OPTIONS (table \'NULLTEST\');\n\nSELECT * FROM nulltest;\n\nERROR:  invalid byte sequence for encoding "UTF8": 0x00\nCONTEXT:  converting column "val" for foreign table scan of "nulltest", row 2\n
Run Code Online (Sandbox Code Playgroud)\n\n

现在最简单的事情是创建一个过滤掉零字符的外表:

\n\n
CREATE FOREIGN TABLE filter_nulltest (\n   id integer OPTIONS (key \'true\') NOT NULL,\n   val varchar(10)\n) SERVER oracle\n   OPTIONS (table \'(SELECT id, replace(val, CHR(0), NULL) FROM nulltest)\');\n\nSELECT * FROM filter_nulltest;\n\n\xe2\x94\x8c\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\xac\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x90\n\xe2\x94\x82 id \xe2\x94\x82  val  \xe2\x94\x82\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\xbc\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\xa4\n\xe2\x94\x82  1 \xe2\x94\x82 sch\xc3\xb6n \xe2\x94\x82\n\xe2\x94\x82  2 \xe2\x94\x82 b\xc3\xb6se  \xe2\x94\x82\n\xe2\x94\x82  3 \xe2\x94\x82 egal  \xe2\x94\x82\n\xe2\x94\x94\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\xb4\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x98\n(3 rows)\n
Run Code Online (Sandbox Code Playgroud)\n\n

另一个效率较低的选项是创建一个函数来捕获并向您报告错误行,以便您可以在 Oracle 端修复它们:

\n\n
CREATE OR REPLACE FUNCTION get_nulltest() RETURNS SETOF nulltest\n   LANGUAGE plpgsql AS\n$$DECLARE\n   v_id integer;\n   n nulltest;\nBEGIN\n   FOR v_id IN SELECT id FROM nulltest\n   LOOP\n      BEGIN\n         SELECT nulltest.* INTO n\n            FROM nulltest\n            WHERE id = v_id;\n         RETURN NEXT n;\n      EXCEPTION\n         WHEN OTHERS THEN\n            RAISE NOTICE \'Caught error % for id=%: %\', SQLSTATE, v_id, SQLERRM;\n      END;\n   END LOOP;\nEND;$$;\n\nSELECT * FROM get_nulltest();\n\nNOTICE:  Caught error 22021 for id=2: invalid byte sequence for encoding "UTF8": 0x00\n\xe2\x94\x8c\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\xac\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x90\n\xe2\x94\x82 id \xe2\x94\x82  val  \xe2\x94\x82\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\xbc\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\xa4\n\xe2\x94\x82  1 \xe2\x94\x82 sch\xc3\xb6n \xe2\x94\x82\n\xe2\x94\x82  3 \xe2\x94\x82 egal  \xe2\x94\x82\n\xe2\x94\x94\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\xb4\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x98\n(2 rows)\n
Run Code Online (Sandbox Code Playgroud)\n