Хабрахабр

Переход через NULL

Многие знают и используют встроенную функцию ISNULL(X, Y), которая заменяет первый аргумент на второй в случае, если он (первый) NULL. Менее употребима обратная встроенная функция NULLIF(X, Y), которая возвращает NULL, если первый аргумент равен второму. Комбинация этих двух функций позволяет избежать использования конструкций IF-ELSE или CASE-WHEN, что делает код компактнее. Если интересно посмотреть пару примеров — добро пожаловать под кат.
Например, вот код, который выводит 10 случайных целых чисел в диапазоне от 1 до 37, и ближайшее большее или равное выведенному числу значение, кратное 6.

SELECT Q.Src, CASE WHEN Q.Src % 6 = 0 THEN Q.Src ELSE Q.Src + (6 - Q.Src % 6) END AS NextTimes6
FROM ( SELECT TOP 10 CONVERT(INT, 1 + 37 * RAND(CHECKSUM(NEWID()))) Src FROM SYSOBJECTS S
) Q

От CASE..WHEN можно избавиться, проделав следующий трюк — обратив в NULL результат выражения Q.Src % 6 в случае, если остаток равен 0, зная, что результат любой операции с NULL равен NULL, и восстанавливая затем обратно NULL до 0 внешней функцией ISNULL:

SELECT Q.Src, Q.Src + ISNULL(6 - NULLIF(Q.Src % 6, 0), 0) AS NextTimes6
FROM ( SELECT TOP 10 CONVERT(INT, 1 + 37 * RAND(CHECKSUM(NEWID()))) Src FROM SYSOBJECTS S
) Q

Еще один пример — разделение строки на две части по пробелу (например, имени из строки ИмяФамилия. Типичная проблема здесь при решении «в лоб» — падение функции LEFT при передаче ей аргумента -1 в качестве значения количества отрезаемых символов в случае, когда пробела в исходной строке не находится (CHARINDEX возвращает 0):

SELECT Q.Src, CASE WHEN CHARINDEX(' ', Q.Src) > 0 THEN LEFT(Q.Src, CHARINDEX(' ', Q.Src) - 1) ELSE Q.Src END AS NameOnly
FROM ( SELECT N'Петр Иванов' AS Src UNION ALL SELECT N'Иван'
) Q

Превращается в:

SELECT Q.Src, LEFT(Q.Src, ISNULL(NULLIF(CHARINDEX(' ', Q.Src), 0) - 1, LEN(Q.Src))) AS NameOnly
FROM ( SELECT N'Петр Иванов' AS Src UNION ALL SELECT N'Иван'
) Q

Приятного SQL-программирования!

Теги
Показать больше

Похожие статьи

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Кнопка «Наверх»
Закрыть