Я переписываю наш класс базы данных (основанный на PDO) и застрял в этом. Меня учили использовать SET NAMES utf8
и SET CHARACTER SET utf8
при работе с UTF-8 в PHP и MySQL.
В PDO я теперь хочу использовать параметр PDO::MYSQL_ATTR_INIT_COMMAND
, но он поддерживает только один запрос.
SET CHARACTER SET utf8
ли SET CHARACTER SET utf8
?
С помощью SET CHARACTER SET utf8
после использования SET NAMES utf8
самом деле сбросит character_set_connection
и collation_connection
на
@@character_set_database
и @@collation_database
соответственно.
В руководстве указано, что
SET NAMES x
эквивалентен
SET character_set_client = x; SET character_set_results = x; SET character_set_connection = x;
и SET CHARACTER SET x
эквивалентно
SET character_set_client = x; SET character_set_results = x; SET collation_connection = @@collation_database;
тогда как SET collation_connection = x
также внутренне выполняет SET character_set_connection = <<character_set_of_collation_x>>
и SET character_set_connection = x
внутренне также выполняет SET collation_connection = <<default_collation_of_character_set_x
.
Таким образом, вы переустанавливаете character_set_connection
на @@character_set_database
и collation_connection
на @@collation_database
. В руководстве объясняется использование этих переменных:
Какой набор символов должен сервер перевести инструкцию после получения?
Для этого сервер использует системные переменные character_set_connection и collation_connection. Он преобразует утверждения, отправленные клиентом от character_set_client к character_set_connection (за исключением строковых литералов, у которых есть интродуктор, такой как _latin1 или _utf8). collation_connection важна для сравнения литеральных строк. Для сравнения строк со значениями столбцов объединение collation_connection не имеет значения, поскольку столбцы имеют собственную сортировку, которая имеет более высокий приоритет сортировки.
Чтобы подвести итог, процедура кодирования / перекодирования MySQL используется для обработки запроса, а его результаты – многоступенчатая:
character_set_client
. character_set_client
в character_set_connection
character_set_connection
в набор символов данного столбца базы данных и использует сортировку столбцов для сортировки и сравнения. character_set_results
(это включает в себя данные результата, а также метаданные результатов, такие как имена столбцов и т. Д.), Таким образом, может быть, что SET CHARACTER SET utf8
не будет достаточным для обеспечения полной поддержки UTF-8. Подумайте о наборе символов базы данных по умолчанию latin1
и столбцах, определенных с помощью utf8
charset, и выполните шаги, описанные выше. Поскольку latin1
не может охватить все символы, которые могут покрывать UTF-8, вы можете потерять информацию о символе на шаге 3 .
latin1
, эти символы будут потеряны при перекодировании с utf8
на latin1
(набор символов базы данных по умолчанию), что приведет к сбою вашего запроса. Поэтому я думаю, что можно с уверенностью сказать, что SET NAMES ...
– это правильный способ справиться с проблемами набора символов. Хотя я мог бы добавить, что правильная настройка ваших переменных MySQL сервера (все обязательные переменные могут быть установлены статически в my.cnf
) освобождает вас от служебных накладных расходов дополнительного запроса, необходимого для каждого подключения.
Из руководства mysql :
SET CHARACTER SET аналогичен SET NAMES, но устанавливает
character_set_connection
иcollation_connection
вcharacter_set_database
иcollation_database
. ОператорSET CHARACTER SET x
эквивалентен этим трех операторам:SET character_set_client = x; SET character_set_results = x; SET collation_connection = @@collation_database;
Поскольку мне нужно поддерживать международные наборы символов, я всегда просто задавал набор символов полей типа текста при создании базы данных.
Я также всегда использовал UTF-8.
В PHP установлено то же самое:
mb_internal_encoding( 'UTF-8' );