PostgreSQL + PHP + UTF8 = неверная последовательность байтов для кодирования

Я переношу db из mysql в postgresql. Значение mysql db по умолчанию - 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_encode() для строк, которые уже являются UTF8, он убивает специальные символы и заставляет их перепутаться, поэтому... что я могу сделать, чтобы заставить это работать?

(точный char висит на нем сейчас "", но вместо того, чтобы просто искать/заменять, я хотел бы найти лучшее решение, чтобы эта любопытная проблема не повторялась)

Ответ 1

Скорее всего, данные в вашей базе данных MySQL не являются UTF8. Это довольно распространенный сценарий. MySQL, по крайней мере, не использовал какую-либо надлежащую проверку вообще на данных, поэтому он принял все, что вы бросили на него как UTF8, пока ваш клиент утверждал, что это UTF8. Возможно, они уже исправили это (или нет, я не знаю, считают ли они его проблемой), но вы, возможно, уже неправильно закодировали данные в db. PostgreSQL, конечно же, выполняет полную проверку при загрузке и, следовательно, может потерпеть неудачу.

Возможно, вы захотите прокормить данные через что-то вроде iconv, которые могут быть установлены для игнорирования неизвестных символов или преобразования их в "наилучшее предположение".

Ответ 2

BTW, строка ASCII точно такая же в UTF-8, потому что они имеют одни и те же первые 127 символов; поэтому "Привет" в ASCII точно так же, как "Привет" в UTF-8, нет необходимости в преобразовании.

Сравнение в таблице может быть UTF-8, но вы не можете получать информацию из него в той же кодировке. Теперь, если у вас возникли проблемы с информацией, которую вы передаете pg_escape_string, возможно, потому, что вы предполагаете, что контент, полученный из MySQL, кодируется в UTF-8, пока он не работает. Я предлагаю вам посмотреть эту страницу в документации по MySQL и посмотреть кодировку вашего соединения; вы, вероятно, извлекаете из таблицы, где сортировка UTF-8, но вы - это что-то вроде Latin-1 (где специальные символы, такие как çéèêöà и т.д., не будут кодироваться в UTF-8).