Mysql: SPLIT function и правильный подсчет количества символов.
Столкнулся на днях с задачкой разделения строки состоящей из нескольких значений, разделенных некоторым разделителем, на отдельные значения на уровне базы данных. Во всех приличных БД все это уже есть из коробки, а вот в MySQL нет. Пришлось написать самому. В общем-то в нете полно решений, но во всех, что я видел, есть один большой недостаток, или даже баг. Заключается он в том, что везде требуется вычислять длину подстрок и делается везде это через функцию LENGTH(). Однако если внимательно прочитать описание этой функции, то можно узнать, что она считает длину строки в БАЙТАХ! То есть если вы используете какую-либо двухбайтную кодировку для хранения строк, например UTF-8 (* вообще станно, если вы до сих пор используете какую-то другую 🙂 *), то эта функция вернет совсем не тот результат, который вы ожидаете. Для того, чтобы избежать этой проблемы, есть другая функция CHAR_LENGTH(), которая делает именно то, что и надо — считает длину строки в символах. Что же до функции разделения строки на значения, то вот мой вариант:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
CREATE FUNCTION `SPLIT_STRING` ( str VARCHAR(2000), delim VARCHAR(12), pos INT ) RETURNS varchar(255) CHARSET utf8 COMMENT 'Разделение строки по делимитеру' RETURN REPLACE( SUBSTRING( SUBSTRING_INDEX(str, delim, pos), CHAR_LENGTH( SUBSTRING_INDEX(str, delim, pos - 1) ) + 1 ), delim, '' ) |
На входе 3 параметра: сама строка, строка-разделитель и номер позиции значения. Если такого разделителя нет, вернется вся строка, позиция значения считается с 1. Вот примеры:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
mysql> select SPLIT_STRING('qwe,asd,zxc', ',', 1); +-------------------------------------+ | SPLIT_STRING('qwe,asd,zxc', ',', 1) | +-------------------------------------+ | qwe | +-------------------------------------+ 1 rows in set (0.01 sec) mysql> select SPLIT_STRING('qwe,asd,zxc', ',', 2); +-------------------------------------+ | SPLIT_STRING('qwe,asd,zxc', ',', 2) | +-------------------------------------+ | asd | +-------------------------------------+ 1 rows in set (0.01 sec) mysql> select SPLIT_STRING('qwe,asd,zxc', '$', 1); +-------------------------------------+ | SPLIT_STRING('qwe,asd,zxc', '$', 1) | +-------------------------------------+ | qwe,asd,zxc | +-------------------------------------+ 1 rows in set (0.01 sec) |
That’s all folks!
MySQL и регистро-зависимость имен в MacOS X
Всем привет.
Столкнулся тут на днях со следующей проблемкой. Я работаю на Mac OS X, и поэтому все необходимое для разработки ПО у меня стоит на моем компе, тот же Апач, Пых (они вообще идут из коробки) ну и Майскуль.
Так вот, решил я для одного нового проекта заюзать MySQL Workbench. Это такая утилита, в которой можно построить UML-схему базы данных, все красиво разрисовать и потом слить эту структуру в конечную БД, так же есть Reverse Engineering. В общем, первое сливание текущей структуры из БД прошло гладко, а вот первая же заливка изменений в БД уже не получилась. Не смотря на то, что Workbench честно показывал изменения, после накатывания аптейта, он все равно продолжал считать, что все структуры разные. Дело в том, что я люблю называть таблицы красивыми именами, отражающими действительность, с заглавными буквами, разве что в дополнение к CamelCase стилю еще разделяю слова символом подчеркивания. Так вот после долгих изучений и изысканий обнаружилось, что установки по умолчанию в MySQL Server на Mac OS, не очень подходят для моего случая.
Как известно, в MySQL, база данных соответствует определенной директории на сервере, и каждая таблица хранится в виде файла (или нескольких в зависимости от движка). Поэтому регистро-чувствительность ОС играет немаловажную роль в обработке регистро-чувствительности при разрешении имен в базе данных. Это означает, что если ваш сервер на винде, то ему пофиг на регистр, в *nix-подобных системах же наоборот, регистр имеет значение, за исключением Mac OS, которая вроде как юникс, а файловая система там HFS+, которая не очень чувствительна к регистру.
В MySQL сервере есть 2 системных переменные которые имеют отношение к регистру имен, это lower_case_file_system и lower_case_table_names. Первая переменная отражает регистрочувствительность файловой системы, где расположено хранилище, оно может принимать всего два значения: OFF — фс чувствительная к регистру и ON — не чувствительна.
Вторая переменная, lower_case_table_names, отражает механизм, как происходит сравнение имен и способ их хранения. 0 означает, что имена сохраняются в том виде, в котором были заданы и сравнение чувствительно к регистру. При значении 1, имена таблиц хранятся в нижнем регистре и сравнение не чувствительно к регистру. В случае 2, имена хранятся как есть, но сравнение происходит в нижнем регистре.
По умолчанию эти переменные принимают вот такие значения на Mac OS X:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
kostik@KOsTIK: ~> mysql Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 6 Server version: 5.1.49 MySQL Community Server (GPL) mysql> select @@lower_case_table_names; +--------------------------+ | @@lower_case_table_names | +--------------------------+ | 2 | +--------------------------+ 1 row in set (0.00 sec) mysql> select @@lower_case_file_system; +--------------------------+ | @@lower_case_file_system | +--------------------------+ | 1 | +--------------------------+ 1 row in set (0.00 sec) |
И вот такие на *nix (проверил на Linux/FreeBSD)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
kostik@linux: ~> mysql Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 49773 Server version: 5.1.51 MySQL Community Server (GPL) by Remi mysql> select @@lower_case_table_names; +--------------------------+ | @@lower_case_table_names | +--------------------------+ | 0 | +--------------------------+ 1 row in set (0.00 sec) mysql> select @@lower_case_file_system; +--------------------------+ | @@lower_case_file_system | +--------------------------+ | 0 | +--------------------------+ 1 row in set (0.00 sec) |
Если почитать описание этих переменных на сайте mysql (тут), то там написаны замечательные рекомендации по выставлению правильных параметров переменной lower_case_table_names. Если лень читать, то основная мысль: если вы используете InnoDB как основной движок, то поставьте везде этот параметр в 1.
Самый простой способ — это прописать эту переменную в файле конфигурации my.cnf в секцию [mysqld] и рестартануть Mysql сервер.
В общем-то я не открыл ничего нового, все это можно найти в офф. документации на сайте, статья: Identifier Case Sensitivity дает более развернутое описание этой ситуации. Рекомендую прочитать.
Вот и все!
Подключение плагинов для мониторинга стороннего ПО в Oracle EM Grid Control на примере MySQL и MS SQL Server.
Это шестой пост из серии «Управление инфраструктурой Oracle с помощью EM Grid Control 11g«. В нем я хочу рассказать о том, как можно расширить возможности EM Grid Control по мониторингу разного стороннего ПО. В EM для этого предусмотрен механизм плагинов мониторинга.