MySQL 4.1+ и любые проблемы с русскими буквами.
Автор: Fix Xxer (PHP Club)
У MySQL версии 4.1 и выше (далее 4.1+) с русскими буквами бывают несколько проблем — рассмотрим их по отдельности.
Симптомы:
Тестирование:
Попробуйте в начале вашего скрипта, но после соединения, выполнить SQL-запрос "SET NAMES кодировка". Где кодировка - та кодировка, в которой у вас (по вашему мнению) данные. Например, для русской Windows кодировки (windows-1251) это будет cp1251, для KOI8-R – koi8r, для UTF-8 – utf8 и так далее. В дальнейшем она будет упоминаться как "кодировка".
Результат тестирования:
Решение:
1) Оставить запрос "SET NAMES кодировка" в начале скрипта. Если скриптов много – см. вариант 2.
2) Заставить MySQL автоматически выполнять этот запрос при каждом соединении с ним.
Для этого необходимо в конфигурационном файле MySQL, в секции [mysqld] добавить следующую строку: init-connect="SET NAMES кодировка".
Однако, следует заметить, что это НЕ будет работать, если пользователь, которым вы подключаетесь к базе имеет привилегию SUPER (а стандартный пользователь root к таким относится, так же как и все созданные через "GRANT ALL PRIVILEGES ON *.* TO ..."). Это сделано для того, чтобы в случае ошибки в этом запросе (а его можно изменить во время работы), хоть кто-то мог подключиться к базе и исправить его.
Внимание! Функция mysqli_client_encoding() и сотоварищи, отображает кодировку клиента на момент соединения и не меняют возвращаемое значение в процессе работы. Поэтому не стоит кричать, что кодировка не меняется. Просто делайте, что говорят и смотрите результат работы скрипта. Получить нужное значение можно SQL-запросом "SHOW VARIABLES LIKE 'character_set_client'".
3) Начиная с версий 4.1.15 и 5.0.13 добавить в секцию [mysqld] или [server] конфигурационного файла MySQL параметр skip-character-set-client-handshake. Этот параметр заставляет сервер игнорировать кодировку, посылаемую клиентом, и использовать указанную серверу. В примере конфигурации ниже этот параметр уже есть.
Симптомы:
Русский текст приходит в скрипт как русский, в консольном клиенте тоже все хорошо. Однако не работает сортировка, перевод в верхний/нижний регистр и т.д. Если применить решение из проблемы №1, то либо русский текст становится вопросами, либо mysql_error() возвращает сообщение похожее на "Illegal mix of collations (latin1_general_ci,IMPLICIT) and (cp1251_general_ci,COERCIBLE)...". В тоже время phpMyAdmin русский текст отображает как "крокозябры" (латинские символы с умляутами и т.д.).
Тестирование:
Попробуйте в phpMyAdmin'е выполнить запрос вида "SELECT CONVERT(CONVERT(поле USING binary) USING кодировка) FROM таблица". Где "таблица" и "поле" - соответствующая таблица и поле с русским текстом, а "кодировка" — кодировка из проблемы №1.
Результат тестирования:
1) Установить для MySQL нужную кодировку по умолчанию.
Внимание! Это решение сработает сработает, только если кодировки не переопределены для базы, таблицы или столбца.
Для этого нужно в конфигурационном файле MySQL в секции [mysqld] добавить следующую строку:
default-character-set=cp1251
2) Сконвертировать таблицы в нужную кодировку.
Про то как конвертировать таблицы с неверными кодировками хорошо написано в мануале MySQL. Повторять здесь то же самое не к чему.
Наша справка:
Список статейУ MySQL версии 4.1 и выше (далее 4.1+) с русскими буквами бывают несколько проблем — рассмотрим их по отдельности.
1. PHP использует неверную кодировку в качестве клиентской.
Симптомы:
- Через phpMyAdmin (здесь и далее подразумевается версия умеющая работать с кодировками, т.е. >= 2.6.0) все по-русски, а в скрипт приходят вопросительные знаки.
- Скрипт, заносящий данные в базу, видит русский нормально, а после вставки, как в правильном скрипте, так и в phpMyAdmin-е — знаки вопросов.
Тестирование:
Попробуйте в начале вашего скрипта, но после соединения, выполнить SQL-запрос "SET NAMES кодировка". Где кодировка - та кодировка, в которой у вас (по вашему мнению) данные. Например, для русской Windows кодировки (windows-1251) это будет cp1251, для KOI8-R – koi8r, для UTF-8 – utf8 и так далее. В дальнейшем она будет упоминаться как "кодировка".
Результат тестирования:
- Если буквы (но необязательно слова) стали русскими, значит, данные в базе лежат в правильной кодировке, сама база эту самую кодировку и использует.
- Если буквы стали русскими, а слова нет ("бнопня"), значит, скрипт ожидает данные в другой русской кодировке — пробуйте другие, пока не получится русских слов.
Решение:
1) Оставить запрос "SET NAMES кодировка" в начале скрипта. Если скриптов много – см. вариант 2.
2) Заставить MySQL автоматически выполнять этот запрос при каждом соединении с ним.
Для этого необходимо в конфигурационном файле MySQL, в секции [mysqld] добавить следующую строку: init-connect="SET NAMES кодировка".
Однако, следует заметить, что это НЕ будет работать, если пользователь, которым вы подключаетесь к базе имеет привилегию SUPER (а стандартный пользователь root к таким относится, так же как и все созданные через "GRANT ALL PRIVILEGES ON *.* TO ..."). Это сделано для того, чтобы в случае ошибки в этом запросе (а его можно изменить во время работы), хоть кто-то мог подключиться к базе и исправить его.
Внимание! Функция mysqli_client_encoding() и сотоварищи, отображает кодировку клиента на момент соединения и не меняют возвращаемое значение в процессе работы. Поэтому не стоит кричать, что кодировка не меняется. Просто делайте, что говорят и смотрите результат работы скрипта. Получить нужное значение можно SQL-запросом "SHOW VARIABLES LIKE 'character_set_client'".
3) Начиная с версий 4.1.15 и 5.0.13 добавить в секцию [mysqld] или [server] конфигурационного файла MySQL параметр skip-character-set-client-handshake. Этот параметр заставляет сервер игнорировать кодировку, посылаемую клиентом, и использовать указанную серверу. В примере конфигурации ниже этот параметр уже есть.
2. MySQL использует неверную кодировку
Симптомы:
Русский текст приходит в скрипт как русский, в консольном клиенте тоже все хорошо. Однако не работает сортировка, перевод в верхний/нижний регистр и т.д. Если применить решение из проблемы №1, то либо русский текст становится вопросами, либо mysql_error() возвращает сообщение похожее на "Illegal mix of collations (latin1_general_ci,IMPLICIT) and (cp1251_general_ci,COERCIBLE)...". В тоже время phpMyAdmin русский текст отображает как "крокозябры" (латинские символы с умляутами и т.д.).
Тестирование:
Попробуйте в phpMyAdmin'е выполнить запрос вида "SELECT CONVERT(CONVERT(поле USING binary) USING кодировка) FROM таблица". Где "таблица" и "поле" - соответствующая таблица и поле с русским текстом, а "кодировка" — кодировка из проблемы №1.
Результат тестирования:
- Если буквы (но необязательно слова) стали русскими, значит текст в базе лежал не в правильной кодировке и его нужно сконвертировать.
- Если буквы стали русскими, а слова нет ("бнопня"), значит неверно выбрана одна из русских кодировок – пробуйте другие, пока не получится русских слов.
1) Установить для MySQL нужную кодировку по умолчанию.
Внимание! Это решение сработает сработает, только если кодировки не переопределены для базы, таблицы или столбца.
Для этого нужно в конфигурационном файле MySQL в секции [mysqld] добавить следующую строку:
default-character-set=cp1251
2) Сконвертировать таблицы в нужную кодировку.
Про то как конвертировать таблицы с неверными кодировками хорошо написано в мануале MySQL. Повторять здесь то же самое не к чему.
Наша справка:
Конфигурационный файл MySQL - применяется для записи и хранения параметров программ MySQL, что исключает необходимость ввода этих параметров в командной строке при каждом вызове программы. Все определенные в конфигурационном файле параметры могут перекрываться параметрами, заданными в командной строке.
В ОС UNIX в качестве конфигурационного файла используется my.cnf, в ОС Windows используется my.ini.
Найти конфигурационный файл можно в корневой директории MySQL (см. местоположение конфигурационного файла MySQL).
Внутри конфигурационных файлов параметры распределены по группам. Например:
Названия групп заключаются в квадратные скобки и обычно соответствуют именам программ. Так, например, группа [mysqld] (в ранних версиях mysql - [server]) соответствует программе mysqld, являющейся сервером MySQL, который обеспечивает клиентским программам доступ к базам данных.
|
[client] user=sampadm password=secret [mysqld] port = 3306 socket = /tmp/mysql.sock |
Названия групп заключаются в квадратные скобки и обычно соответствуют именам программ. Так, например, группа [mysqld] (в ранних версиях mysql - [server]) соответствует программе mysqld, являющейся сервером MySQL, который обеспечивает клиентским программам доступ к базам данных.