插入时出现Postgres错误-错误:编码“ UTF8”的字节序列无效:0x00


76

将数据从mysql插入postgres时出现以下错误。

我是否必须从输入数据中手动删除所有空字符?有没有办法让postgres为我做这件事?

ERROR: invalid byte sequence for encoding "UTF8": 0x00

Answers:


66

PostgreSQL不支持在文本字段中存储NULL(\ 0x00)字符(这显然与数据库NULL值完全不同)。

来源:http//www.postgresql.org/docs/9.1/static/sql-syntax-lexical.html#SQL-SYNTAX-STRINGS-UESCAPE

如果需要存储NULL字符,则必须使用bytea字段-该字段应存储所需的任何内容,但不支持对其进行文本操作。

鉴于PostgreSQL在文本值中不支持它,因此没有很好的方法来删除它。您可以将数据导入bytea,然后使用特殊功能(可能在perl或其他功能中)将其转换为文本,但是在加载之前进行预处理可能会更容易。


范例: CREATE TABLE store_bytes ( key INTEGER NOT NULL, data bytea NOT NULL );
zengr 2015年

19

只是正则表达式输出空字节:

s/\x00//g;

1
空字符串被视为空字节吗?不会replaceAll("s/\x00//g","")导致将它们替换为其他null吗?
Alexandru Severin

3
空字符串不被视为空字节。空字节值是实际字符,但不可见。
Simon Steinberger

14

如果使用的是Java,则只需在插入之前替换x00字符,如下所示:

myValue.replaceAll("\u0000", "")

Csaba在以下帖子中提供了解决方案并进行了解释:

https://www.postgresql.org/message-id/1171970019.3101.328.camel%40coppola.muc.ecircle.de

分别:

在Java中,您的字符串中实际上可以有一个“ 0x0”字符,这是有效的unicode。因此,它被转换为UTF8中的字符0x0,而该字符又被接受,因为服务器使用以空值终止的字符串...因此,唯一的方法是确保字符串不包含字符'\ u0000'。


因此,postgres不兼容UTF-8。好像我整夜都在忙着解决生产问题,因为他们撒谎了。
斯科特·凯里

1

您可以先将数据插入Blob字段,然后使用以下功能复制到文本字段

CREATE OR REPLACE FUNCTION blob2text() RETURNS void AS $$
Declare
    ref record;
    i integer;
Begin
    FOR ref IN SELECT id, blob_field FROM table LOOP

          --  find 0x00 and replace with space    
      i := position(E'\\000'::bytea in ref.blob_field);
      WHILE i > 0 LOOP
        ref.bob_field := set_byte(ref.blob_field, i-1, 20);
        i := position(E'\\000'::bytea in ref.blobl_field);
      END LOOP

    UPDATE table SET field = encode(ref.blob_field, 'escape') WHERE id = ref.id;
    END LOOP;

End; $$ LANGUAGE plpgsql; 

-

SELECT blob2text();

1

仅此正则表达式对我有用:

sed 's/\\0//g'

因此,当您获取数据时,请执行以下操作:$ get_data | sed 's/\\0//g'这将在不输出数据的情况下0x00


0

如果您需要在文本字段中存储空字符,并且不想更改除文本之外的数据类型,那么您也可以按照我的解决方案进行操作:

插入之前:

myValue = myValue.replaceAll("\u0000", "SomeVerySpecialText")

选择后:

myValue = myValue.replaceAll("SomeVerySpecialText","\u0000")

我已经将“ null”用作我的SomeVerySpecialText,我确信我的值中根本没有任何“ null”字符串。


0

当使用COPY并且转义的字符串包含NULL值(00)时,也会发生这种错误,例如:

"H\x00\x00\x00tj\xA8\x9E#D\x98+\xCA\xF0\xA7\xBBl\xC5\x19\xD7\x8D\xB6\x18\xEDJ\x1En"

如果使用时COPY未指定format 'CSV'postgres,则默认为format 'text'。与反冲的交互作用不同,请参见文本格式

如果您使用COPY或请file_fdw确保指定format 'CSV'以避免此类错误。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.