Строковые функции ASCII() и ORD() в MySql. Выборка по алфавиту.
Главная » Блог » Строковые функции ASCII() и ORD() в MySql. Выборка по алфавиту.Наша компания на данный момент занимается разработкой игрового портала, с каталогом игр, в котором есть около 5000 игр. В техническом задании указано использовать выборку по алфавиту, базу данных MySql.
В этой статье я хотел осветить некоторые моменты подобных MySql запросов. Для тестирования возможностей нам понадобится таблица, где мы создадим одно поле `name`, которое должно быть обязательно индексом, так как по этому полю мы будем производить выборки.
CREATE TABLE IF NOT EXISTS `engine_game` ( `name` varchar(300) COLLATE utf8_unicode_ci NOT NULL, KEY `name` (`name`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
Заполним это поле разными данными, чтобы можно было протестировать.
ASCII() возвращает нам ASCII-код крайнего слева символа. Функция ORD() также возвращает ASCII-код крайнего слева символа, но при условии что символ не является многобайтным. Если он таковым является, то код рассчитывается по формуле, которую вы можете посмотреть в официальной документации.
Итак, давайте на примерах сравним их, но прежде сделаем в консоли:
mysql> SET NAMES utf8;
У меня кодировка базы UTF8. Если ваша кодировка другая, подставьте ее туда.
mysql> SELECT `name`, ASCII(`name`) as ascii_name, ord(`name`) as ord_name FROM `engine_game`; +---------------------------------+------------+----------+ | name | ascii_name | ord_name | +---------------------------------+------------+----------+ | Einherjar: The Viking's Blood | 69 | 69 | | Joyous Rebel | 74 | 74 | | Joyous Rebel 2 | 74 | 74 | | 7.62 | 55 | 55 | | A Game of Dwarves: Star Dwarves | 65 | 65 | +---------------------------------+------------+----------+ 5 rows in set (0.00 sec)
Как видим, обе функции возвращают нам одинаковые значения. Давайте теперь попробуем то же самое с русским текстом.
mysql> SELECT `name`, ASCII(`name`) as ascii_name, ord(`name`) as ord_name FROM `engine_game`; +----------------------------------------------------------+------------+----------+ | name | ascii_name | ord_name | +----------------------------------------------------------+------------+----------+ | Горький-18: Мужская работа для PC | 208 | 53395 | | За гранью: Две души | 208 | 53399 | +----------------------------------------------------------+------------+----------+ 2 rows in set (0.00 sec)
Значения изменились! Более того, ASCII функция возвращает на любую букву русского алфавита диапазон кодов от 208 до 209, когда работа идет в UTF8! Следовательно использование функции ASCII() в нашем случае отпадает!
Попробуем теперь сделать выборку через функцию ORD().
mysql> SELECT `name` FROM `engine_game` WHERE ORD(`name`) = ORD('З'); +------------------------------------+ | name | +------------------------------------+ | За гранью: Две души | +------------------------------------+ 1 row in set (0.00 sec) mysql> SELECT `name` FROM `engine_game` WHERE ORD(`name`) = ORD('з'); +-------------------+ | name | +-------------------+ | за гранью | +-------------------+ 1 row in set (0.00 sec)
Из этого примера видно, что данная функция чувствительна к регистру, и для того, чтобы ее использовать для выборки, придется использовать 2 раза.
mysql> SELECT `name` FROM `engine_test` WHERE ORD(`name`) = ORD('з') OR ORD(`name`) = ORD('З'); +------------------------------------+ | name | +------------------------------------+ | за гранью | | За гранью: Две души | +------------------------------------+ 2 rows in set (0.00 sec)
Из этого можно сделать вывод, что использование данной функции для выборки по алфавиту — не самое рациональное решение. Зато ее можно использовать для выборки от 0 до 9:
mysql> SELECT `name` FROM `engine_test` WHERE ORD(`name`) >= ORD('0') AND ORD(`name`) <= ORD('9'); +------+ | name | +------+ | 0 | | 1 | | 2 | | 3 | | 4 | | 5 | | 6 | | 7 | | 8 | | 9 | +------+ 10 rows in set (0.00 sec)
В следующей статье я рассмотрю функцию LEFT(), выражение вида "LIKE '{string}%'".