Работа MySQL со строками
Дата: 21.01.2007
Автор: Павел Пушкарев , paulus (at) sqlinfo (dot) ru
Начиная с версии 4.0, сервер MySQL поддерживает преобразование кодировок
символов. Эта статья рассказывает о том, что такое кодировки, сопоставления
и о том, как работать с ними применительно к серверу MySQL.
Русскоязычные кодировки
Традиционно в России использовались четыре кодировки для представления
русских символов:
- CP866 (DOS)
- KOI8-R
- MacCyrillic
- CP1251 (Windows)
Эти четыре кодировки имеют как общие черты, так и различия. Во-первых, все
они используют один байт информации для хранения одного символа. Во-вторых,
они совместимы с кодировкой 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 байт (впрочем, это
не накладывает особых ограничений).
Дата публикации: 21.01.2007
© Все права на данную статью принадлежат порталу SQLInfo.ru. Перепечатка в интернет-изданиях разрешается только с указанием автора и прямой ссылки на оригинальную статью. Перепечатка в бумажных изданиях допускается только с разрешения редакции.
|