В реализациях языка SQL может быть выполнено неявное преобразование типов. Так, например, в T-SQL при сравнении или комбинировании значений типов smallint и int, данные типа smallint неявно преобразуются к типу int. Подробно о явном и неявном преобразовании типов в MS SQL Server можно прочитать в BOL.
Пример. Вывести среднюю цену ПК-блокнотов с предваряющим текстом "средняя цена = ".
Попытка выполнить запрос
SELECT 'Средняя цена = ' + AVG(price) FROM laptop; |
SELECT 'Средняя цена = ' + CAST(AVG(price) AS CHAR(15)) FROM laptop; |
Средняя цена = 1410.44 |
CAST(<выражение> AS <тип данных>)
При этом следует иметь в виду, во-первых, что не любые преобразования типов возможны
(стандарт содержит таблицу допустимых преобразований типов данных). Во-вторых,
результат функции CAST для значения выражения, равного NULL, тоже будет NULL.
Рассмотрим еще один пример: определить средний год спуска на воду кораблей из таблицы Ships. Запрос
SELECT AVG(launched) FROM ships; |
SELECT CAST(AVG(launched) AS NUMERIC(6,2)) FROM ships; |
SELECT AVG(CAST(launched AS NUMERIC(6,2))) FROM ships; |
SELECT CAST(AVG(CAST(launched AS NUMERIC(6,2))) AS NUMERIC(6,2)) FROM ships; |
SELECT CAST(AVG(launched*1.0) AS NUMERIC(6,2)) FROM ships; |
Т.е. мы использовали неявное преобразование целочисленного аргумента к точному числовому типу (EXACT NUMERIC), умножив его на вещественную единицу, после чего применили явное приведения типа результата агрегатной функции.
Аналогичные преобразования типа можно выполнить с помощью функции CONVERT:
SELECT CONVERT(NUMERIC(6,2),AVG(launched*1.0)) FROM ships; |
Функция CONVERT имеет следующий синтаксис:
CONVERT (<тип данных>[(<длина>)], <выражение> [, <стиль>])
Основное отличие функции CONVERT от функции CAST состоит в том, что первая позволяет форматировать данные (например, темпоральные данные типа datetime) при преобразовании их к символьному типу и указывать формат при обратном преобразовании. Разные целочисленные значения необязательного аргумента стиль соответствуют определенным форматам. Рассмотрим следующий пример
SELECT CONVERT(char(25),CONVERT(datetime,'20030722')); |
Jul 22 2003 12:00AM |
стиль | формат |
1 | 07/22/03 |
11 | 03/07/22 |
3 | 22/07/03 |
121 | 2003-07-22 00:00:00.000 |
Пусть требуется вывести список всех моделей ПК с указанием их цены. При этом если модель отсутствует в продаже (нет в таблице РС), то вместо цены вывести текст: "Нет в наличии".
Список всех моделей ПК с ценами можно получить с помощью запроса:
SELECT DISTINCT product.model, price FROM product LEFT JOIN pc c
ON product.model=c.model WHERE product.type='pc'; |
model | price |
1121 | 850 |
1232 | 350 |
1232 | 400 |
1232 | 600 |
1233 | 600 |
1233 | 950 |
1233 | 980 |
1260 | 350 |
2111 | NULL |
2112 | NULL |
SELECT DISTINCT product.model,
CASE WHEN price IS NULL THEN 'Нет в наличии' ELSE CAST(price AS CHAR(20)) END price FROM product LEFT JOIN pc c ON product.model=c.model WHERE product.type='pc' |
model | price |
1121 | 850 |
1232 | 350 |
1232 | 400 |
1232 | 600 |
1233 | 600 |
1233 | 950 |
1233 | 980 |
1260 | 350 |
2111 | Нет в наличии |
2112 | Нет в наличии |
Оператор CASE может быть использован в одной из двух синтаксических форм записи:
1-я форма
CASE <проверяемое выражение>
WHEN <сравниваемое выражение 1>
THEN <возвращаемое значение 1>
…
WHEN <сравниваемое выражение N>
THEN <возвращаемое значение N>
[ELSE <возвращаемое значение>]
END
2-я форма
CASE
WHEN <предикат 1>
THEN <возвращаемое значение 1>
…
WHEN <предикат N>
THEN <возвращаемое значение N>
[ELSE <возвращаемое значение>]
END
Все предложения WHEN должны иметь одинаковую синтаксическую форму, т.е. нельзя смешивать первую и вторую формы.
При использовании первой синтаксической формы условие WHEN удовлетворяется,
как только значение проверяемого выражения станет равным значению выражения,
указанного в предложении WHEN. При использовании второй синтаксической формы условие WHEN
удовлетворяется, как только предикат принимает значение TRUE.
При удовлетворении условия оператор CASE возвращает значение, указанное в соответствующем предложении THEN.
Если ни одно из условий WHEN не выполнилось, то будет использовано значение, указанное в предложении ELSE.
При отсутствии ELSE, будет возвращено NULL-значение. Если удовлетворены несколько условий, то будет возвращено
значение предложения THEN первого из них.
В приведенном выше примере была использована вторая форма оператора CASE.
Заметим, что для проверки на NULL стандарт предлагает более короткую форму оператора
- COALESCE. Этот оператор имеет произвольное число параметров и возвращает
значение первого, отличного от NULL. Для двух параметров оператор COALESCE(A, B)
эквивалентен следующему оператору CASE:
CASE WHEN A IS NOT NULL THEN A ELSE B END
Решение рассмотренного выше примера при использовании оператора COALESCE можно переписать следующим образом:SELECT DISTINCT product.model,
COALESCE(CAST(price as CHAR(20)),'Нет в наличии') price FROM product LEFT JOIN pc c ON product.model=c.model WHERE product.type='pc'; |
SELECT DISTINCT model, price,
CASE price WHEN (SELECT MAX(price) FROM pc) THEN 'Самый дорогой' WHEN (SELECT MIN(price) FROM pc) THEN 'Самый дешевый' ELSE 'Средняя цена' END comment FROM pc ORDER BY price; |
model | price | comment |
1232 | 350 | Самый дешевый |
1260 | 350 | Самый дешевый |
1232 | 400 | Средняя цена |
1233 | 400 | Средняя цена |
1233 | 600 | Средняя цена |
1121 | 850 | Средняя цена |
1233 | 950 | Средняя цена |
1233 | 980 | Самый дорогой |
Начало | Упражнения SELECT (рейтинговые этапы) | Упражнения DML | Разработчики |