MySQL кодування
Використання кодувань у MySQL.
Насамперед я сходив на http://dev.mysql.com/doc/ і скачав звідти мануал по 5.1.
Встановлюємо MySQL 5.1
Нехай це не "правильний" спосіб установки MySQL-сервера, зате швидкий і робочий.
Отже, sockstat показала, що сервер працює, а установка говорить про те, що сервер абсолютно незайманий. Чим це загрожує? Кодування за замовчуванням виставлено англомовні, а отже, будуть проблеми при використанні кирилиці. Але як це розпізнати? Перевіряємо:
Перш за все використовуємо тестову базу, яка вже є на сервері, потім створюємо в ній таблицю і вставляємо в неї три слова українською, про кодування ми поки що нічого не знаємо і знати не хочемо))).
Поки все добре і райдужно, жодних помилок немає, пробуємо зробити вибірку:
Як видно, запити працюють абсолютно коректно, де ж граблі. Виявляється ми вже стоїмо на них:
Запит на вибірку зі зворотним сортуванням привів до того, що записи просто вивелися в зворотному порядку, але не за абеткою. До удару граблів залишаються лічені секунди, але поки що розтягнемо задоволення :) Спершу відповімо на запитання - чому поля не сортуються за абеткою? MySQL має потужний і багатий механізм для роботи з міжнародними наборами символів, але... але звідки MySQL дізнається, що наші символи - є український алфавіт, ми ж качалианглійськуверсію? Нічого не залишається, як йти колупати мануал на предмет кодувань.
Після того, як завантажився 16-метровий мануал, можна не полінуватися і прочитати першу пару-трійку сторінок із змістом )), а можна просто зробити пошук на предметcharsetабоcharacter set. Не має значення, але через деякий час можна знайти розділ9.1.2. Character Sets andCollations in MySQL, в якому написано багато і цікаво, а, головне, змістовно про те, як можна і потрібно працювати з кодуванням.
Розставляючи точки над і,Character Set- транслюється як "кодування", аCollation- порівняння. В чому різниця? Порівняння – це правила порівняння букв кодування. Порівняння працюють тільки в рамках кодування, і не можна порівнювати дані в латиниці за правилами кирилиці. Поясню на прикладі: ми, як побачимо пізніше, внесли дані в таблицю на латиниці, а потрібно сортувати на кирилиці, для чого можна використовувати ключове словоcollate:
MySQL відмовляється це робити. але чому? Тому що latin1 не підтримує порівняння в кирилиці, а доступні "порівняння" можна побачити так:
Ні про яку кирилицю не може йтися й мови. Куди копати. У створення таблиці!
Ага! За умовчанням при створенні таблиці було взято кодування latin1, отже, якщо ми змінимо таблицю і вкажемо їй, що треба використовувати кирилістичне кодування, то все почне працювати. У мануалі написано приклад зміни кодування таблиці, використовуємо його:
Ок! Перевіряємо, що вийшло.
Хм.. знову та сама помилка, але звідки їй взятися.
Ого, структура таблиці різко змінилася, тепер у неї задане одне кодування, а біля поля зовсім інше.. :(( Порив ще мануал, можна змінити і кодування стовпця:
Ну ось. Злий кодування latin1 немає і близько, можна перевіряти наш пологовий будинок )))
І ось той страшний удар граблями, що так довго відтягувався! Уважний читач міг помітити, що коли було зроблено спробу примусово змінити кодування стовпця, що містить дані в latin1, то на кожен запис, який містить українські літери, у MySQL був варнінг! Це був крик про те, щосервер не знає, яким чином можна перекласти дані з latin1 в CP1251, та й кращого способу, ніж замінити символи не latin1 питаннями, він не знайшов :))). Пологовий будинок безповоротно втрачений тому, що тепер замість кирилиці в базі містяться питання.
Цього можна було уникнутиНасправді, ситуація, коли спочатку виставлено неправильне кодування, зустрічається часто-густо. Симптоми можна виявити так:
Саме ці змінні відповідають за дефолтні значення кодувань.
character_set_client- кодування, в якому дані надходитимуть від клієнтаcharacter_set_connection- кодування за умовчанням для всього, що в рамках з'єднання не має кодуванняcharacter_set_database> - кодування за умовчанням для базcharacter_set_filesystem- кодування для роботи з файловою системою (LOAD DATA INFILE, SELECT . INTO OUTFILE, і т.д.)character_set_results- кодування, в якому буде обрано результатcharacter_set_server- кодування, в якому працює серверcharacter_set_system- кодування, в якому задаються ідентифікатори MySQL, завжди UTF8character_sets_dir- папка з кодуванням
Найбільш значущі для простих користувачів такі змінні: character_set_client, character_set_results, character_set_connection. Оскільки саме вони відповідають за внесення, отримання інформації та створення таблиць/баз відповідно. Якими вони можуть бути?
Будь-яке з цих кодувань можна користуватись на свій смак. Зазвичай українськомовні користувачі віддають перевагу cp1251 або utf8, але по суті, неважливо, в якому кодуванні зберігаються дані, важливо, щоб воно було спочатку правильно вказане і дані були коректно внесені.
Мануал пропонує нам три варіантизавдання кодувань: 1. Через names 2. Через безпосередньо змінні character_set_* 3. Через налаштування самого сервера
УВАГА.Перші два варіанти працюють тількив рамках поточного з'єднання. Це означає, що при наступному підключенні всі настройки повернуться до початкового стану! Щоб не виставляти кодування щоразу, потрібно скористатися третім варіантом.
Варіант 1 - Через names
Ну, тут все ясно, три найпотрібніші кодування в одному)))
Варіант 2 - Через безпосередньо змінні character_set_*
Більш детальна настройка, ніж names.
Варіант 3 - Через налаштування самого сервераТут можна піти двома шляхами - або через конфіг файл:
При конфігурації можна також встановити кодування за замовчуванням
Але краще, коли кодування налаштовується у з'єднанні.
Цей варіант підходить майже для всіх випадків, за винятком деяких особливих ситуацій, наприклад коли порівняння, виставлене за замовчуванням, не доречне для деяких полів. Приклад - поле зберігання пароля, необхідно порівнювати його з урахуванням регістру, тоді як за замовчуванням виставляється порівняння без урахування регістру.
Правильний варіант роботи з MySQL
Таким чином, клієнт працює в KOI8-R, але дані зберігаються в CP1251, MySQL знає про це і робить перекодування на льоту.
Ну і на ціпок:
Вибирати дані можна в будь-якому кодуванні, так само, як і вносити, головне - правильно повідомити MySQL.
РазомЯ тільки переказав одну главу мануалу :)))