【问题标题】:Postgres error on insert - ERROR: invalid byte sequence for encoding "UTF8": 0x00插入时出现 Postgres 错误 - 错误:编码“UTF8”的字节序列无效:0x00
【发布时间】:2010-11-23 18:36:42
【问题描述】:

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

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

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

【问题讨论】:

    标签: postgresql


    【解决方案1】:

    当使用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'。这与反冲有不同的交互作用,请参阅text format

    如果您使用的是COPYfile_fdw,请务必指定format 'CSV' 以避免此类错误。

    【讨论】:

      【解决方案2】:

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

      插入前:

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

      选择后:

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

      我使用“null”作为我的 SomeVerySpecialText,我确信我的值中根本不会有任何“null”字符串。

      【讨论】:

        【解决方案3】:

        只有这个正则表达式对我有用:

        sed 's/\\0//g'
        

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

        【讨论】:

          【解决方案4】:

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

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

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

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

          分别:

          在 Java 中,您实际上可以在字符串中包含“0x0”字符,并且 那是有效的Unicode。所以这被翻译成字符 0x0 UTF8,反过来又不被接受,因为服务器使用 null 终止的字符串......所以唯一的方法是确保你的字符串 不包含字符“\u0000”。

          【讨论】:

          • 所以,postgres 不兼容 UTF-8。看来我会因为他们撒谎而整晚都在解决制作问题。
          【解决方案5】:

          您可以先将数据插入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();
          

          【讨论】:

            【解决方案6】:

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

            s/\x00//g;
            

            【讨论】:

            • 是否将空字符串视为空字节? replaceAll("s/\x00//g","") 不会导致用其他空值替换它们吗?
            • 空字符串不被视为空字节。空字节值是实际字符,但不可见。
            【解决方案7】:

            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 );
            猜你喜欢
            • 2022-01-26
            • 2022-07-28
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2019-04-09
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多