Я переписываю наш класс базы данных (основанный на 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' );