Кодування і рядки в mysql - статті

російськомовні кодування

Традиційно в Росії використовувалися чотири кодування для представлення російських символів:

Ці чотири кодування мають як загальні риси, так і відмінності. По-перше, всі вони використовують один байт інформації для зберігання одного символу. По-друге, вони сумісні з кодуванням latin1, тобто у них збігаються перші 128 байт таблиці кодування. Розрізняються ж значення символів з встановленим верхнім бітом (тобто зі значеннями 128-255).

Навіть чотири кодування символів для однієї мови - це дуже багато. Спочатку люди не надавали цьому значення, але в останні кілька років це стало не так. Виникли різноманітні проблеми переносимості програм, і люди вирішили створити узагальнюючі кодування, що містять символи всіх мов світу (в тому числі, зрозуміло, і російського).

Так була створена кодування Unicode (UCS-2). Зрозуміло, неможливо розмістити дуже велика кількість символів в 8 бітах, тому в цьому кодуванні використовуються 2 байта (тобто 16 біт) на кожний символ. Рядки в цьому кодуванні, безумовно, займають більше місця, ніж у старих кодуваннях, але зате додатки, що використовують такі рядки, дуже легко переносяться на інші мови.

Не дивлячись на введення UCS-2, деякі проблеми все-таки залишилися. По-перше, це вже вказане збільшення довжини рядка. Люди, які використовують тільки латинські символи, не могли для себе зрозуміти, чому вони повинні використовувати 16 біт для позначення символів, які вмістяться в 7 біт. По-друге, 65536 символів все одно не вистачає для позначення всіх використовуваних символів на планеті.

Для подолання цих труднощів, була створена кодування зі змінною довжиною символу UTF-8. У цьому кодуванні використовується 1 байт для позначення перших 128 символів (тобто символів, що входять в latin1). Якщо встановлено верхню біт першого байта, то використовується другий байт (тобто російські літери в цьому кодуванні займають 2 байти). Якщо встановлено верхню біт другого байта, то використовується третій байт (і туди входять різноманітні ієрогліфи і інші східні символи) і так далі.

Таке кодування по-перше, може розмістити в себе будь-яку кількість символів (тому що вона дозволяє збільшувати кількість байт динамічним чином). По-друге, для англійської мови використовується 1 байт, і це дуже приємно для англомовних країн. Східні країни не дуже люблять це кодування, тому що їм доводиться використовувати 3 байта для позначення своїх символів (в UCS-2 вони використовують тільки два).

зіставлення символів

Деякі додатки (включаючи і MySQL, про який мова піде далі) використовують не тільки кодування, але і зіставлення символів. Справа в тому, що деякі символи деякі мови вважають однаковими (а іноді вважаються однаковими символ або послідовність символів). Наприклад, «ü» в німецькій мові може бути записаний як «ue». З іншого боку, в шведській мові той же символ може бути записаний як «uy».

У російській мові можна, наприклад, вважати однаковими букви «е» і «е» (як часто роблять в офіційних документах). Також часто буває у нагоді не розрізняти великі і маленькі букви (які мають різний код в будь-якому кодуванні).

Зіставлення впливає саме на те, як додаток працює з сукупністю символів, воно впливає на порядок сортування і на порівняння символів. Зрозуміло, зіставлення залежить від кодування символів.

Кодування символів в MySQL

У сервері MySQL у кожного рядка є своя кодування і зіставлення. При створенні таблиці, Ви можете вказати кодування і зіставлення, в яких будуть збережені рядки всередині таблиці. Ви можете навіть вказувати ці параметри для кожного поля таблиці. наприклад:

CREATE TABLE enctest (
str1 CHAR (10) CHARSET koi8r,
str2 CHAR (15) COLLATE utf8_general_ci
);

В даному прикладі створюється таблиця з двома полями, одне з яких буде зберігатися в кодуванні KOI8-R (і з зіставленням за замовчуванням). Друге поле матиме зіставлення utf8_general_ci і кодування UTF-8 (кодування визначається в порівнянні, тому що зіставлення залежить від неї).

Список доступних кодувань і зіставлень Ви можете отримати, відповідно, командами

SHOW CHARACTER SET;
SHOW COLLATION;

Кодування за замовчуванням і зміна кодування рядків в MySQL

Якщо Ви не хочете явно вказувати кодування рядків в таблиці, Ви можете для цієї таблиці вказати кодування символів за замовчуванням:

CREATE TABLE enctest2 (
str1 CHAR (10),
str2 CHAR (15)
) DEFAULT CHARSET cp1251;

В даному випадку, обидві рядки будуть створені в кодуванні CP1251. Ви можете вказувати кодування окремих рядків і в разі зазначення кодування за замовчуванням.

Ви також можете змінити кодування символів для конкретного поля таблиці:

ALTER TABLE enctest2 MODIFY str1 CHAR (10) CHARSET utf8;

В даному випадку, в поле str1 змінюється кодування і всі рядки перекодуються. Врахуйте, що якщо Ви змінюєте кодування за замовчуванням для таблиці, то рядки в ній не перекодуються, Ви просто впливаєте на створення інших полів в цій таблиці.

Зіставлення в MySQL

В MySQL для кожного кодування є принаймні одне зіставлення (а зазвичай, кілька). Для того, щоб зрозуміти, чим вони відрізняються, вони всі мають дуже докладні назви.

Назва кожного зіставлення починається з назви відповідної кодування (наприклад, utf8_). Далі йде специфікація зіставлення (найчастіше, йде просте зіставлення, general, що не ідентифікує літери) і вказівка ​​на чутливість до регістру (cs - case sensitive - чутливе до регістру, ci - case insensitive - не відчутно).

Окремо варто відзначити бінарні зіставлення (binary). Якщо рядки зіставляються бінарним чином, то між ними не робиться ніяких зіставлень і перетворень. Такі рядки не будуть перетворені командою SET NAMES (див. Далі). Бінарні зіставлення особливо зручно використовувати при переході з MySQL 3.23, який не підтримував кодування і який вказує, що всі таблиці знаходяться в кодуванні latin1 (не дивлячись на те, що таблиці можуть містити дані, скажімо, в KOI8-R).

Клієнтські кодування MySQL

Сервер MySQL автоматично змінює кодування рядків при занесенні даних в таблицю і при вибірці даних з таблиці. При цьому він використовує дані з системних змінних, таких, як character_set_client. Список всіх змінних, що впливають на кодування, Ви можете отримати, виконавши команду

SHOW VARIABLES LIKE 'char%';

Ви можете вказувати або змінні по-одиночці, або змінювати їх відразу великим набором (як потрібно в більшості випадків):

SET NAMES koi8r;

Після того, як сервер отримає таку команду, він буде очікувати, що Ви будете передавати йому всі рядки в кодуванні KOI8-R і буде автоматично переводити виводяться їм рядки в це кодування.

Це зручно тоді, коли сервер за замовчуванням працює не в тій кодуванні, яку Ви очікуєте (наприклад, в KOI8-R, а Ви хочете виводити інформацію на сайті в CP1251).

Зберігання інформації в MySQL

MySQL зберігає інформацію відповідно до того, яке кодування ви вказали. Так сервер виділяє по 1 байту на кожен символ для однобайтових кодувань (при цьому CHAR (10) займає завжди 10 байт, VARCHAR (10) займає від 1 до 11 байт в залежності від довжини рядка, 1 зайвий байт витрачається на зберігання довжини рядка).

Для кодування UCS-2 сервер виділяє по 2 байта на кожен символ. Для кодування UTF-8 сервер виділяє різну кількість байт для різних символів (відповідно до кодуванням) в разі VARCHAR і 3 байта на кожен символ в разі CHAR. Таким чином, в UTF-8 рядок CHAR (10) завжди займає 30 байт, а VARCHAR (10) - від 1 до 31 байта.Прі цьому ні в якому разі при застосуванні UTF-8 сервер не може зберігати символи довжиною від 4 байт ( втім, це не накладає особливих обмежень).