Работа с значениями NULL
К NULL -значениям нужно привыкнуть. По идее, NULL обозначает отсутствующее или неизвестное значение и обрабатывается отличным от других значений образом. Проверить значение на равенство NULL с помощью обычных арифметических операторов сравнения (=, < или <>) нельзя. Это отлично иллюстрирует следующий запрос:
mysql> SELECT 1 = NULL, 1 <> NULL, 1 < NULL, 1 > NULL;
+----------+-----------+----------+----------+ | 1 = NULL | 1 <> NULL | 1 < NULL | 1 > NULL | +----------+-----------+----------+----------+ | NULL | NULL | NULL | NULL | +----------+-----------+----------+----------+
Очевидно, что от таких сравнений значащих результатов ожидать нечего. Вместо этого нужно пользоваться операторами IS NULL и IS NOT NULL :
mysql> SELECT 1 IS NULL, 1 IS NOT NULL;
+-----------+---------------+ | 1 IS NULL | 1 IS NOT NULL | +-----------+---------------+ | 0 | 1 | +-----------+---------------+
Отметим, что два значения NULL считаются равными при выполнении команды GROUP BY .
В MySQL 0 или NULL приравнивается к логическому false, а все остальное - к true. По умолчанию значение "истина" для булевого оператора равно 1.
При выполнении команды ORDER BY значения NULL всегда располагаются в самом начале списка результатов, даже при использовании параметра DESC .
Именно из-за того, что при работе с NULL действуют особые правила, в предыдущем разделе для поиска умерших животных использовалось выражение death IS NOT NULL , а не death <> NULL .
Сравнение по шаблонам
В MySQL реализовано стандартное для SQL сравнение по шаблонам, а также особый тип такого сравнения - он основан на использовании выражений, подобных применяющимся в служебных программах Unix (таких, как vi, grep и sed).
В SQL при сравнении по шаблону символ '_" обозначает любой одиночный символ, а "%" - определенное количество символов (включая ноль символов). В MySQL в SQL-шаблонах по умолчанию не учитывается регистр символов. При работе с шаблонами SQL использование операторов = или <> не допускается, вместо этого применяются операторы сравнения LIKE или NOT LIKE .
Найти все имена, начинающиеся с 'b", можно следующим образом:
mysql> SELECT * FROM pet WHERE name LIKE "b%";
+--------+--------+---------+------+------------+------------+ | name | owner | species | sex | birth | death | +--------+--------+---------+------+------------+------------+ | Buffy | Harold | dog | f | 1989-05-13 | NULL | | Bowser | Diane | dog | m | 1989-08-31 | 1995-07-29 | +--------+--------+---------+------+------------+------------+
Найти все имена, заканчивающиеся на 'fy", можно следующим образом:
mysql> SELECT * FROM pet WHERE name LIKE "%fy";
+--------+--------+---------+------+------------+-------+ | name | owner | species | sex | birth | death | +--------+--------+---------+------+------------+-------+ | Fluffy | Harold | cat | f | 1993-02-04 | NULL | | Buffy | Harold | dog | f | 1989-05-13 | NULL | +--------+--------+---------+------+------------+-------+
Найти все имена, содержащие 'w", можно следующим образом:
mysql> SELECT * FROM pet WHERE name LIKE "%w%";
+----------+-------+---------+------+------------+------------+ | name | owner | species | sex | birth | death | +----------+-------+---------+------+------------+------------+ | Claws | Gwen | cat | m | 1994-03-17 | NULL | | Bowser | Diane | dog | m | 1989-08-31 | 1995-07-29 | | Whistler | Gwen | bird | NULL | 1997-12-09 | NULL | +----------+-------+---------+------+------------+------------+
Найти все имена, содержащие ровно пять символов, можно при помощи шаблонного символа "_":
mysql> SELECT * FROM pet WHERE name LIKE "_____";
+-------+--------+---------+------+------------+-------+ | name | owner | species | sex | birth | death | +-------+--------+---------+------+------------+-------+ | Claws | Gwen | cat | m | 1994-03-17 | NULL | | Buffy | Harold | dog | f | 1989-05-13 | NULL | +-------+--------+---------+------+------------+-------+
Во втором типе шаблонов, предусмотренных в MySQL, используются расширенные регулярные выражения. При поиске совпадений на основе такого шаблона шаблоном нужно пользоваться операторами REGEXP и NOT REGEXP (или их синонимами - RLIKE и NOT RLIKE ).
Ниже приведены некоторые характеристики расширенных регулярных выражений:
"." обозначает любой символ.
Класс символов "[...]" обозначает любой из символов в скобках. Например, "[abc]" обозначает "a", "b" или "c". Набор символов можно обозначить с помощью дефиса. "[a-z]" обозначает любую букву нижнего регистра, а "[0-9]" - любую цифру.
"*" обозначает ноль или более экземпляров символа, стоящего перед ним. Например, "x*" обозначает любое количество символов "x", "[0-9]*" обозначает любое количество цифр, а ".*" - любое количество любых символов.
Для шаблона выдается совпадение, если поисковый контекст обнаружен в любой из частей значения, в котором производится поиск (для шаблонов SQL совпадение выдается только в случае, если совпадает все значение).
"Закрепить" шаблон так, чтобы проверять совпадения с началом или концом значения можно с помощью символов "^" (начало) или "$" (конец), которые располагаются в начале или в конце шаблона соответственно.
Чтобы продемонстрировать работу регулярных выражений, приведенные выше запросы LIKE здесь переписаны с использованием REGEXP .
Найти все имена, начинающиеся с "b", можно при помощи символа "^", привязывающего шаблон к началу имени:
mysql> SELECT * FROM pet WHERE name REGEXP "^b";
+--------+--------+---------+------+------------+------------+ | name | owner | species | sex | birth | death | +--------+--------+---------+------+------------+------------+ | Buffy | Harold | dog | f | 1989-05-13 | NULL | | Bowser | Diane | dog | m | 1989-08-31 | 1995-07-29 | +--------+--------+---------+------+------------+------------+
В версиях MySQL до 3.23.4 REGEXP учитывает регистр символов, и приведенный запрос не возвратит никаких результатов. Для поиска символов "b" верхнего или нижнего регистра воспользуйтесь следующим запросом:
mysql> SELECT * FROM pet WHERE name REGEXP "^[bB]";
Начиная с версии MySQL 3.23.4, заставить REGEXP учитывать регистр символов можно с помощью ключевого слова BINARY . В этом запросе положительный результат поиска будет получен только при обнаружении символа "b" нижнего регистра в начале имени:
mysql> SELECT * FROM pet WHERE name REGEXP BINARY "^b";
Найти все имена, заканчивающиеся на "fy", можно при помощи символа "$", привязывающего шаблон к концу имени:
mysql> SELECT * FROM pet WHERE name REGEXP "fy$";
+--------+--------+---------+------+------------+-------+ | name | owner | species | sex | birth | death | +--------+--------+---------+------+------------+-------+ | Fluffy | Harold | cat | f | 1993-02-04 | NULL | | Buffy | Harold | dog | f | 1989-05-13 | NULL | +--------+--------+---------+------+------------+-------+
Найти все имена, содержащие символ 'w" любого регистра, можно так:
mysql> SELECT * FROM pet WHERE name REGEXP "w";
+----------+-------+---------+------+------------+------------+ | name | owner | species | sex | birth | death | +----------+-------+---------+------+------------+------------+ | Claws | Gwen | cat | m | 1994-03-17 | NULL | | Bowser | Diane | dog | m | 1989-08-31 | 1995-07-29 | | Whistler | Gwen | bird | NULL | 1997-12-09 | NULL | +----------+-------+---------+------+------------+------------+
Поскольку регулярное выражение выдает положительный результат при совпадении шаблона с любым фрагментом значения, в приведенном выше примере привязывать поиск к любому из концов имени для сравнения полного значения с шаблоном, как это пришлось бы делать для шаблона SQL, не нужно.
Найти все имена, содержащие ровно пять символов, можно, если привязать поиск к началу и концу имени с помощью символов "^" и '$" и поставить пять символов "." между ними:
mysql> SELECT * FROM pet WHERE name REGEXP "^.....$";
+-------+--------+---------+------+------------+-------+ | name | owner | species | sex | birth | death | +-------+--------+---------+------+------------+-------+ | Claws | Gwen | cat | m | 1994-03-17 | NULL | | Buffy | Harold | dog | f | 1989-05-13 | NULL | +-------+--------+---------+------+------------+-------+
Предыдущий запрос можно записать и при помощи оператора "{n}"("повторить-n -раз"):
mysql> SELECT * FROM pet WHERE name REGEXP "^.{5}$";
+-------+--------+---------+------+------------+-------+ | name | owner | species | sex | birth | death | +-------+--------+---------+------+------------+-------+ | Claws | Gwen | cat | m | 1994-03-17 | NULL | | Buffy | Harold | dog | f | 1989-05-13 | NULL | +-------+--------+---------+------+------------+-------+
1 2 3 4 5 6 7
8 8 8
|