代码之家  ›  专栏  ›  技术社区  ›  Ian Baget

PostgreSQL+PHP+UTF8=编码的字节序列无效

  •  10
  • Ian Baget  · 技术社区  · 15 年前

    我正在将数据库从mysql迁移到postgresql。mysql数据库的默认排序规则是UTF8,postgres也使用UTF8,我用pg_escape_string()对数据进行编码。不管出于什么原因,我遇到了一些关于糟糕编码的可怕错误:

    pg_query() [function.pg-query]: Query failed: ERROR: invalid byte sequence for encoding "UTF8": 0xeb7374 HINT: This error can also happen if the byte sequence does not match the encoding expected by the server, which is controlled by "client"

    我一直在四处摸索,试图弄明白这一点,并注意到php正在做一些奇怪的事情;如果字符串中只有ascii字符(例如“hello”),则编码为ascii。如果字符串包含任何非ascii字符,则表示编码为UTF8(例如“Hëllo”)。

    当我在已经是utf8的字符串上使用utf8_encode()时,它会杀死特殊字符,并将它们都弄乱,所以。。我该怎么做才能让它正常工作?

    (现在挂起它的确切字符是“ëë½”,但我不只是搜索/替换,而是想找到更好的解决方案,这样这种问题就不会再发生了)

    2 回复  |  直到 15 年前
        1
  •  6
  •   Magnus Hagander    15 年前

    很可能,MySQL数据库中的数据不是UTF8。这是很常见的情况。MySQL至少以前根本不对数据进行任何适当的验证,所以只要客户机声称它是UTF8,它就会接受你扔给它的任何东西作为UTF8。他们可能已经确定了现在(或者不,我不知道他们是否认为这是一个问题),但是你可能已经在数据库中错误地编码了数据。当然,PostgreSQL在加载时会执行完全验证,因此可能会失败。

    您可能希望通过iconv之类的工具提供数据,该工具可以设置为忽略未知字符,或将它们转换为“最佳猜测”。

        2
  •  1
  •   Percutio    15 年前

    顺便说一句,ASCII字符串在UTF-8中完全相同,因为它们共享相同的前127个字符;所以ASCII中的“Hello”与UTF-8中的“Hello”完全相同,不需要转换。

    表中的排序规则可能是UTF-8,但您可能无法以相同的编码从中获取信息。现在如果你对你提供的信息有问题 pg_escape_string 这可能是因为您假设从MySQL获取的内容是以UTF-8编码的,而不是。我建议你看看 this page on MySQL documentation 并查看连接的编码;您可能是从一个排序规则为UTF-8的表中获取数据,但连接类似于拉丁语-1(其中的特殊字符,例如 çéèêöà etc不会被编码为UTF-8)。