Читаем MySQL: руководство профессионала полностью

$link = mysql_connect($host, $usr, $pwd);

mysql_select_db($db);

if (mysql_error()) {

print "Database ERROR: " . mysql_error();

}

mysql_query("SET NAMES 'utf8'", $link);

?>


В этом случае мы использовали SET NAMES, чтобы изменить character_set_client, character_set_connection и character_set_results.


Правильно использовать более нового расширения mysqli, а не старого mysql. При использовании mysqli предыдущий пример мог бы быть переписан как показано здесь:


$link = new mysqli($host, $usr, $pwd, $db);

if (mysqli_connect_errno()) {

printf("Connect failed: %s\n", mysqli_connect_error());

exit();

}

$link->query("SET NAMES 'utf8'");

?>


Другая проблема, с которой часто сталкиваются в прикладных программах на PHP: что делать с предположениями, сделанными браузером. Иногда добавление или изменение тэга достаточно, чтобы исправить проблему: например, чтобы обеспечить, чтобы агент пользователя интерпретировал содержание страницы как UTF-8, Вы должны включить в HTML-страницы.


10.11.11: Я обновился до MySQL 5.1. Как я могу возвращаться к поведению, аналогичному MySQL 4.0, относительно наборов символов?


В MySQL 4.0 имелся один глобальный набор символов для клиента и сервера, который назначался администратором. Это изменилось в MySQL 4.1. Когда пользователь соединяется, он посылает серверу имя набора символов, который требуется использовать. Сервер использует это имя, чтобы установить переменные системы character_set_client, character_set_results и character_set_connection. В действительности сервер выполняет операцию SET NAMES, использующую имя набора символов. Эффект этого: Вы не можете управлять набором символов пользователя, запуская mysqld с параметром --character-set-server=utf8. Однако, некоторые заказчики сказали, что предпочитают поведение MySQL 4.0. Чтобы делать возможным сохранить это поведение, разработчики добавили в mysqld переключатель --character-set-client-handshake, который может быть выключен с --skip-character-set-client-handshake. Если Вы запускаете mysqld с --skip-character-set-client-handshake, то, когда пользователь соединяется, это посылает серверу имя набора символов, который требуется использовать. Однако, сервер проигнорирует этот запрос от пользователя.


Например, предположите, что Ваш любимый набор символов сервера latin1 (вряд ли это так в области CJK, но это значение по умолчанию). Предположите далее, что пользователь использует utf8 потому, что операционная система пользователя поддерживает. Теперь запустите сервер с latin1 как заданный по умолчанию набор символов:


mysqld --character-set-server=latin1


Затем запустите пользователя с заданным по умолчанию набором символов utf8:


mysql --default-character-set=utf8


Текущие параметры настройки могут быть выяснены, рассматривая вывод SHOW VARIABLES:


mysql> SHOW VARIABLES LIKE 'char%';

+--------------------------+----------------------------------------+

| Variable_name | Value |

+--------------------------+----------------------------------------+

| character_set_client | utf8 |

| character_set_connection | utf8 |

| character_set_database | latin1 |

| character_set_filesystem | binary |

| character_set_results | utf8 |

| character_set_server | latin1 |

| character_set_system | utf8 |

| character_sets_dir | /usr/local/mysql/share/mysql/charsets/ |

+--------------------------+----------------------------------------+

8 rows in set (0.01 sec)


Теперь остановите пользователя, а затем и сервер, используя mysqladmin. Затем запустите сервер снова, но на сей раз сообщите, чтобы он не менял набор символов:

mysqld --character-set-server=utf8 --skip-character-set-client-handshake


Запустите пользователя с utf8 еще раз как заданный по умолчанию набор символов, а затем отобразите текущие параметры настройки:


mysql> SHOW VARIABLES LIKE 'char%';

+--------------------------+----------------------------------------+

| Variable_name | Value |

+--------------------------+----------------------------------------+

| character_set_client | latin1 |

| character_set_connection | latin1 |

| character_set_database | latin1 |

| character_set_filesystem | binary |

| character_set_results | latin1 |

| character_set_server | latin1 |

| character_set_system | utf8 |

| character_sets_dir | /usr/local/mysql/share/mysql/charsets/ |

+--------------------------+----------------------------------------+

8 rows in set (0.01 sec)


Как Вы можете видеть, сравнивая отличия выводов SHOW VARIABLES, сервер игнорирует начальные установки пользователя, если используется опция --skip-character-set-client-handshake.


10.11.12: Почему некоторые LIKE и поиск FULLTEXT с символами CJK срываются?


Имеется очень простая проблема с поисками LIKE на столбцах BINARY и BLOB: мы должны знать конец символа. С многобайтовыми наборами символов, различные символы могли бы иметь различные длины. Например, в utf8, A требует один байт, но уГЪ требует трех байтов, как показано здесь:

+-------------------------+---------------------------+

| OCTET_LENGTH(_utf8 'A') | OCTET_LENGTH(_utf8 'уГЪ') |

+-------------------------+---------------------------+

| 1 | 3 |

+-------------------------+---------------------------+

1 row in set (0.00 sec)


Если мы не знаем, где символьные концы, то мы не знаем, где начинаются следующие символы даже в очень простых поисках, типа LIKE '_A%'. Решение состоит в том, чтобы использовать регулярный набор символов CJK или преобразовываться в набор символов CJK перед сравнением.


Это одна причина, почему MySQL не может позволять кодирование несуществующих символов. Если это не строго относительно отклонения, то не имеется никакого способа узнавать, где символы заканчиваются.


Для поисков FULLTEXT мы должны знать, где слова начинаются и заканчиваются. С западными языками это редко проблема, потому что большинство (если не все) они используют пробел, чтобы идентифицировать конец слова. Однако, это не так с азиатской записью.


10.11.13: Какие наборы символов CJK доступны в MySQL?


Список наборов символов CJK может изменяться в зависимости от Вашей версии MySQL. Например, набор символов eucjpms не обеспечивался до MySQL 5.0.3. Однако, так как имя соответствующего языка появляется в столбце DESCRIPTION для каждого входа в таблице INFORMATION_SCHEMA.CHARACTER_SETS, Вы можете получать текущий список всех не-Unicode наборов символов CJK, используя этот запрос:


mysql> SELECT CHARACTER_SET_NAME, DESCRIPTION FROM

– > INFORMATION_SCHEMA.CHARACTER_SETS

– > WHERE DESCRIPTION LIKE '%Chinese%' OR

– > DESCRIPTION LIKE '%Japanese%' OR DESCRIPTION LIKE '%Korean%'

– > ORDER BY CHARACTER_SET_NAME;

+--------------------+---------------------------+

| CHARACTER_SET_NAME | DESCRIPTION |

+--------------------+---------------------------+

| big5 | Big5 Traditional Chinese |

| cp932 | SJIS for Windows Japanese |

| eucjpms | UJIS for Windows Japanese |

| euckr | EUC-KR Korean |

| gb2312 | GB2312 Simplified Chinese |

| gbk | GBK Simplified Chinese |

| sjis | Shift-JIS Japanese |

| ujis | EUC-JP Japanese |

+--------------------+---------------------------+

8 rows in set (0.01 sec)


10.11.14: Как я узнаю, является ли символ X доступным во всех наборах символов?


Большинство упрощеннных китайских и японских символов Kana появляются во всех CJK-наборах символов. Эта сохраненная процедура принимает символ UCS-2 Unicode, преобразует это во все другие наборы символов и отображает результаты в шестнадцатеричном формате.


DELIMITER //

CREATE PROCEDURE p_convert(ucs2_char CHAR(1) CHARACTER SET ucs2)

BEGIN

CREATE TABLE tj (ucs2 CHAR(1) character set ucs2,

utf8 CHAR(1) character set utf8,

big5 CHAR(1) character set big5,

cp932 CHAR(1) character set cp932,

eucjpms CHAR(1) character set eucjpms,

euckr CHAR(1) character set euckr,

gb2312 CHAR(1) character set gb2312,

gbk CHAR(1) character set gbk,

sjis CHAR(1) character set sjis,

ujis CHAR(1) character set ujis);

INSERT INTO tj (ucs2) VALUES (ucs2_char);

UPDATE tj SET utf8=ucs2, big5=ucs2, cp932=ucs2, eucjpms=ucs2, euckr=ucs2,

gb2312=ucs2, gbk=ucs2, sjis=ucs2, ujis=ucs2;


/* If there's a conversion problem, UPDATE will produce a warning. */

SELECT hex(ucs2) AS ucs2, hex(utf8) AS utf8, hex(big5) AS big5,

hex(cp932) AS cp932, hex(eucjpms) AS eucjpms, hex(euckr) AS euckr,

hex(gb2312) AS gb2312, hex(gbk) AS gbk, hex(sjis) AS sjis,

hex(ujis) AS ujis FROM tj;

DROP TABLE tj;

END//


Ввод может быть любым одиночным символом ucs2 или значением отметки кода (шестнадцатеричное представление) для этого символа. Например, из списка Unicode кодирования и имен ucs2 ( http://www.unicode.org/Public/UNIDATA/UnicodeData.txt) мы знаем, что символ Katakana Pe появляется во всех CJK-наборах символов, и что значение отметки кода 0x30da. Если мы используем это значение как параметр для p_convert(), результат показывается здесь:


mysql> CALL p_convert(0x30da)//

+------+--------+------+-------+---------+-----+------+------+------+------+

| ucs2 | utf8 | big5 | cp932 | eucjpms |euckr|gb2312| gbk | sjis | ujis |

+------+--------+------+-------+---------+-----+------+------+------+------+

| 30DA | E3839A | C772 | 8379 | A5DA |ABDA |A5DA | A5DA | 8379 | A5DA |

+------+--------+------+-------+---------+-----+------+------+------+------+

1 row in set (0.04 sec)


Так как ни одно из значений столбца не 3F, то есть символ вопросительного знака (?), мы знаем, что каждое преобразование сработало.


10.11.15: Почему CJK-строки не сортируются правильно в Unicode? (I)


Иногда люди наблюдают, что результат поиска utf8_unicode_ci или ucs2_unicode_ci, либо сортировка ORDER BY не то, что они ожидали. Хотя мы никогда не исключаем возможность, что имеется ошибка, в прошлом было установлено, что много людей не читают правильно стандартную таблицу весов для алгоритма объединения Unicode. MySQL использует таблицу, найденную на http://www.unicode.org/Public/UCA/4.0.0/allkeys-4.0.0.txt. Это не первая таблица, которую Вы найдете, начав с unicode.org, потому что MySQL использует старую таблицу 4.0.0 allkeys , а не более новую 4.1.0. Это потому, что разработчики очень осторожны относительно изменения упорядочения, которое воздействует на индексы, чтобы не вызывать ситуации типа сообщенной в

Глюке #16526, иллюстрируемой следующим образом:


mysql< CREATE TABLE tj (s1 CHAR(1) CHARACTER SET utf8 COLLATE

utf8_unicode_ci);

Query OK, 0 rows affected (0.05 sec)


mysql> INSERT INTO tj VALUES ('уБМ'),('уБЛ');

Query OK, 2 rows affected (0.00 sec)

Records: 2 Duplicates: 0 Warnings: 0

mysql> SELECT * FROM tj WHERE s1 = 'уБЛ';

+-----+

| s1 |

+-----+

| уБМ |

| уБЛ |

+-----+

2 rows in set (0.00 sec)


Символ в первой строке результатов не тот, который мы искали. Почему MySQL находит это? Сначала мы ищем значение отметки кода Unicode, которое является возможным, читая шестнадцатеричный номер для ucs2-версии символов:


mysql> SELECT s1, HEX(CONVERT(s1 USING ucs2)) FROM tj;

+-----+-----------------------------+

| s1 | HEX(CONVERT(s1 USING ucs2)) |

+-----+-----------------------------+

| уБМ | 304C |

| уБЛ | 304B |

+-----+-----------------------------+

2 rows in set (0.03 sec)


Теперь мы ищем 304B и 304C в таблице 4.0.0 allkeys и находим эти строки:

304B; [.1E57.0020.000E.304B] # HIRAGANA LETTER KA

304C; [.1E57.0020.000E.304B][.0000.0140.0002.3099] # HIRAGANA LETTER GA; QQCM


Официальные имена Unicode (после метки #) сообщают нам японский символ (Hiragana), неофициальную классификацию (символ, цифра или знак препинания) и западный идентификатор (KA или GA, произносимые и непроизносимые компоненты той же самой пары символов). Более важен первичный вес (primary weight , первый шестнадцатеричный номер внутри квадратных скобок) 1E57 на обеих строках. Для сравнений в поиске и сортировке MySQL использует только первичный вес, игнорируя все другие числа. Это означает, что мы сортируем уБМ и уБЛ правильно, согласно Unicode спецификации. Если мы хотим отличить их, мы должны будем использовать non-UCA (Unicode Collation Algorithm) объединение (utf8_unicode_bin или utf8_general_ci), либо сравнивать значения HEX(), либо применять ORDER BY CONVERT(s1 USING sjis). Быть правильным, согласно Unicode, конечно, недостаточно: человек, который представил на рассмотрение ошибку, был прав. Мы планируем добавлять другое объединение для японских символов согласно стандарту JIS X 4061, в котором высказанные/невысказанные пары символов, подобные KA/GA, являются различимыми для целей упорядочения.


10.11.16: Почему CJK-строки не сортируются правильно в Unicode? (дополнение)


Если Вы используете Unicode (ucs2 или utf8) и Вы знаете порядок сортировки Unicode, но MySQL все еще сортирует Вашу таблицу неправильно, то Вы должны сначала проверить набор символов таблицы:


mysql> SHOW CREATE TABLE t\G

******************** 1. row ******************

Table: t

Create Table: CREATE TABLE `t` (`s1` char(1) CHARACTER SET ucs2 DEFAULT NULL)

ENGINE=MyISAM DEFAULT CHARSET=latin1

1 row in set (0.00 sec)


Так как набор символов правильный, давайте посмотрим то, какую информацию таблица INFORMATION_SCHEMA.COLUMNS может обеспечивать относительно этого столбца:


mysql> SELECT COLUMN_NAME, CHARACTER_SET_NAME, COLLATION_NAME

– > FROM INFORMATION_SCHEMA.COLUMNS

– > WHERE COLUMN_NAME = 's1' AND TABLE_NAME = 't';

+-------------+--------------------+-----------------+

| COLUMN_NAME | CHARACTER_SET_NAME | COLLATION_NAME |

+-------------+--------------------+-----------------+

| s1 | ucs2 | ucs2_general_ci |

+-------------+--------------------+-----------------+

1 row in set (0.01 sec)


Вы можете видеть, что объединение ucs2_general_ci вместо ucs2_unicode_ci. Причина того, почему это так, может быть найдена, используя SHOW CHARSET, как показано здесь:


mysql> SHOW CHARSET LIKE 'ucs2%';

+---------+---------------+-------------------+--------+

| Charset | Description | Default collation | Maxlen |

+---------+---------------+-------------------+--------+

| ucs2 | UCS-2 Unicode | ucs2_general_ci | 2 |

+---------+---------------+-------------------+--------+

1 row in set (0.00 sec)


Для ucs2 и utf8 заданное по умолчанию объединение: general. Чтобы определять объединение Unicode, используйте COLLATE ucs2_unicode_ci.


10.11.17: Почему мои дополнительные символы отклонены MySQL?


MySQL не поддерживает дополнительные символы, то есть символы, которые нуждаются больше, чем в 3 байтах для UTF-8. Пакет поддерживает только Basic Multilingual Plane/Plane 0 . Только несколько очень редких символов Han дополнительны; поддержка для них необыкновенна. Это привело к отчетам типа найденного в Глюке #12600, который авторы отклонили как не ошибка. С utf8 мы должны усечь входную строку, когда сталкиваемся с байтами, которые не понимаем. Иначе мы не знали бы, какой длины многобайтовый символ.


Одно возможное решение должно использовать ucs2 вместо utf8, когда символы изменены на вопросительные знаки. Однако, никакое усечение не происходит. Вы можете также изменять тип данных на BLOB или BINARY, которые не выполняют никакую проверку правильности.


10.11.18: Разве это не должен быть CJKV?


Нет. Термин CJKV (Chinese Japanese Korean Vietnamese) обращается к вьетнамским наборам символов, которые содержат Han (изначально китайские) символы. MySQL не имеет никакого плана, чтобы поддерживать старый вьетнамский вариант, использующий символы Han. MySQL поддерживает современный вьетнамский вариант с символами Western.


Глюк #4745 просьба о специализированном вьетнамском объединении, которое может быть добавлено в будущем, если имеется достаточная потребность в этом.


10.11.19: MySQL позволяет символам CJK использоваться в именах баз данных и таблиц?


Эта проблема отфиксирована в MySQL 5.1, автоматически переписывая имена соответствующих каталогов и файлов.


Например, если Вы создаете базу данных цео на сервере, чья операционная система не поддерживает CJK в именах каталогов, MySQL создает каталог @0w@00a5@00ae, который является только причудливым способом кодирования E6A5AE, то есть шестнадцатеричное представление для Unicode-символа цео. Однако, если Вы выполняете инструкцию SHOW DATABASES, Вы можете видеть, что база данных перечислена как цео.


10.11.20: Где я могу находить переводы руководства по MySQL на китайский, корейский и японский языки?


Упрощенная китайская версия руководства для MySQL 5.1.12 может быть найдена на http://dev.mysql.com/doc/#chinese-5.1. Японская для MySQL 4.1 может быть получена с http://dev.mysql.com/doc/#japanese-4.1.


10.11.21: Где я могу получать справку по CJK и связанным проблемам в MySQL?


Следующие ресурсы доступны:


Перечень групп пользователей MySQL может быть найден на http://dev.mysql.com/user-groups/.


Вы можете входить в контакт с инженером сбыта в MySQL KK Japan:

Tel: +81(0)3-5326-3133

Fax: +81(0)3-5326-3001

Email: dsaito@mysql.com


Просмотр показывает запросы в отношении проблем набора символов на http://tinyurl.com/y6xcuf.


Посетите форум "MySQL Character Sets, Collation, Unicode" на http://forums.mysql.com/list.php?103.

Перейти на страницу:

Похожие книги

C# 4.0: полное руководство
C# 4.0: полное руководство

В этом полном руководстве по C# 4.0 - языку программирования, разработанному специально для среды .NET, - детально рассмотрены все основные средства языка: типы данных, операторы, управляющие операторы, классы, интерфейсы, методы, делегаты, индексаторы, события, указатели, обобщения, коллекции, основные библиотеки классов, средства многопоточного программирования и директивы препроцессора. Подробно описаны новые возможности C#, в том числе PLINQ, библиотека TPL, динамический тип данных, а также именованные и необязательные аргументы. Это справочное пособие снабжено массой полезных советов авторитетного автора и сотнями примеров программ с комментариями, благодаря которым они становятся понятными любому читателю независимо от уровня его подготовки. Книга рассчитана на широкий круг читателей, интересующихся программированием на C#.Введите сюда краткую аннотацию

Герберт Шилдт

Программирование, программы, базы данных
C++ Primer Plus
C++ Primer Plus

C++ Primer Plus is a carefully crafted, complete tutorial on one of the most significant and widely used programming languages today. An accessible and easy-to-use self-study guide, this book is appropriate for both serious students of programming as well as developers already proficient in other languages.The sixth edition of C++ Primer Plus has been updated and expanded to cover the latest developments in C++, including a detailed look at the new C++11 standard.Author and educator Stephen Prata has created an introduction to C++ that is instructive, clear, and insightful. Fundamental programming concepts are explained along with details of the C++ language. Many short, practical examples illustrate just one or two concepts at a time, encouraging readers to master new topics by immediately putting them to use.Review questions and programming exercises at the end of each chapter help readers zero in on the most critical information and digest the most difficult concepts.In C++ Primer Plus, you'll find depth, breadth, and a variety of teaching techniques and tools to enhance your learning:• A new detailed chapter on the changes and additional capabilities introduced in the C++11 standard• Complete, integrated discussion of both basic C language and additional C++ features• Clear guidance about when and why to use a feature• Hands-on learning with concise and simple examples that develop your understanding a concept or two at a time• Hundreds of practical sample programs• Review questions and programming exercises at the end of each chapter to test your understanding• Coverage of generic C++ gives you the greatest possible flexibility• Teaches the ISO standard, including discussions of templates, the Standard Template Library, the string class, exceptions, RTTI, and namespaces

Стивен Прата

Программирование, программы, базы данных
Programming with POSIX® Threads
Programming with POSIX® Threads

With this practical book, you will attain a solid understanding of threads and will discover how to put this powerful mode of programming to work in real-world applications. The primary advantage of threaded programming is that it enables your applications to accomplish more than one task at the same time by using the number-crunching power of multiprocessor parallelism and by automatically exploiting I/O concurrency in your code, even on a single processor machine. The result: applications that are faster, more responsive to users, and often easier to maintain. Threaded programming is particularly well suited to network programming where it helps alleviate the bottleneck of slow network I/O. This book offers an in-depth description of the IEEE operating system interface standard, POSIX (Portable Operating System Interface) threads, commonly called Pthreads. Written for experienced C programmers, but assuming no previous knowledge of threads, the book explains basic concepts such as asynchronous programming, the lifecycle of a thread, and synchronization. You then move to more advanced topics such as attributes objects, thread-specific data, and realtime scheduling. An entire chapter is devoted to "real code," with a look at barriers, read/write locks, the work queue manager, and how to utilize existing libraries. In addition, the book tackles one of the thorniest problems faced by thread programmers-debugging-with valuable suggestions on how to avoid code errors and performance problems from the outset. Numerous annotated examples are used to illustrate real-world concepts. A Pthreads mini-reference and a look at future standardization are also included.

David Butenhof

Программирование, программы, базы данных