
- •Простой оператор select
- •Предикаты
- •Предикаты сравнения
- •Предикат in
- •Объединение
- •Пересечение и разность
- •Предикат exists
- •Получение итоговых значений
- •Предложение group by
- •Предложение having
- •Использование в запросе нескольких источников записей
- •Использование ключевых слов some (any) и all с предикатами сравнения
- •Переименование столбцов и вычисления в результирующем наборе
- •Преобразование типов и оператор cast
- •Оператор case
- •Предикат like
- •Предикат like и регулярные выражения
- •Использование значения null в условиях поиска
- •Функция datepart
- •Нумерация строк в соответствии с порядком, заданном значениями первичного ключа
- •Функция row_number
- •Декартово произведение
- •Коррелирующие подзапросы
Преобразование типов и оператор cast
В реализациях языка SQL может быть выполнено неявное преобразование типов. Так, например, в Transact-SQL при сравнении или комбинировании значений типов smallint и int, данные типа smallint неявно преобразуются к типу int. Подробно о явном и неявном преобразовании типов в SQL Server можно прочитать в BOL.
Пример1: Вывести среднюю цену портативных компьютеров с предваряющим текстом «средняя цена = ».
Попытка выполнить запрос
SELECT 'Средняя цена = '+AVG(price)
FROMLaptop
приведет к сообщению об ошибке:
Implicit conversion from data type varchar to money is not allowed. Use the CONVERT function to run this query.
(«Не допускается неявное преобразование типа varchar к типу money. Используйте для выполнения этого запроса функцию CONVERT».)
Это сообщение означает, что система не может выполнить неявное преобразование типа varchar к типу money. В подобных ситуациях может помочь явное преобразование типов. При этом, как указано в сообщении об ошибке, можно воспользоваться функцией CONVERT. Однако эта функция не стандартизована, поэтому в целях переносимости рекомендуется использовать стандартное выражение CAST. С него и начнем.
Итак, если переписать наш запрос в виде
SELECT 'Средняя цена = '+ CAST(AVG(price) AS CHAR(15))
FROM Laptop
в результате получим то, что требовалось:
Средняя цена = 1003.33
Мы использовали выражение явного преобразования типов CAST для приведения среднего значения цены к строковому представлению.
Синтаксис выражения CAST очень простой
CAST(<выражение> AS <тип данных>)
Следует иметь в виду, во-первых, что не любые преобразования типов возможны (стандарт содержит таблицу допустимых преобразований типов данных). Во-вторых, результат функции CAST для значения выражения, равного NULL, тоже будет NULL.
Пример2: Определить средний год спуска на воду кораблей из таблицы Ships.
Запрос:
SELECT AVG(launched)
FROM Ships;
даст результат 1926. В принципе все правильно, так как мы получили в результате то, что просили — год. Однако среднее арифметическое будет составлять примерно 1926,2381. Тут следует напомнить, что агрегатные функции (за исключением функции COUNT, которая всегда возвращает целое число) наследуют тип данных обрабатываемых значений. Поскольку поле launched — целочисленное, мы и получили среднее значение с отброшенной дробной частью (заметьте — не округленное).
А если нас интересует результат с заданной точностью, скажем, до двух десятичных знаков? Применение выражения CAST к среднему значению ничего не даст по указанной выше причине. Действительно,
SELECT CAST(AVG(launched) AS NUMERIC(6,2))
FROM Ships;
вернет значение 1926.00. Следовательно, CAST нужно применить к аргументу агрегатной функции:
SELECT AVG(CAST(launched AS NUMERIC(6,2)))
FROM Ships;
Результат — 1926.238095. Опять не то. Причина состоит в том, что при вычислении среднего значения было выполнено неявное преобразование типа. Сделаем еще один шаг:
SELECT CAST(AVG(CAST(launched AS NUMERIC(6,2)))AS NUMERIC(6,2))
FROM Ships;
В результате получим то, что нужно — 1926.24. Однако это решение выглядит очень громоздко. Заставим неявное преобразование типа поработать на нас:
SELECT CAST(AVG(launched*1.0) AS NUMERIC(6,2))
FROM Ships;
Аналогичные преобразования типа можно выполнить с помощью функции SQL Server CONVERT:
SELECT CONVERT(NUMERIC(6,2),AVG(launched*1.0))
FROM Ships;
Функция CONVERT имеет следующий синтаксис:
CONVERT (<тип_данных[(<длина>)]>, <выражение> [, <стиль>])
Основное отличие функции CONVERT от функции CAST состоит в том, что первая позволяет форматировать данные (например, темпоральные данные типа datetime) при преобразовании их к символьному типу и указывать формат при обратном преобразовании. Разные целочисленные значения необязательного аргумента стиль соответствуют различным типам форматов. Рассмотрим следующий пример:
SELECT CONVERT(char(25), CONVERT(datetime,'20030722'));
Здесь мы преобразуем строковое представление даты к типу datetime, после чего выполняем обратное преобразование, чтобы продемонстрировать результат форматирования. Поскольку значение аргумента стиль не задано используется значение по умолчанию (0 или 100). В результате получим: Jul 22 2003 12:00AM
Ниже приведены некоторые другие значения аргумента стиль и результат, полученный на приведенном выше примере. Заметим, что увеличение значения стиль на 100 приводит к четырехзначному отображению года.
1 |
07/22/03 |
11 |
03/07/22 |
3 |
22/07/03 |
121 |
2003-07-22 00:00:00.000 |
Есть одна особенность использования оператора CAST в SQL Server, связанная с преобразованием числа к его строковому представлению. Что произойдет, если число символов в числе превышает размер строки? Например,
SELECT CAST(1234.6 AS VARCHAR(5))
Следует ожидать, что мы получим сообщение об ошибке. Правильно, вот это сообщение:
Arithmetic overflow error converting numeric to data type varchar.
(«Ошибка арифметического переполнения при преобразовании числа к типу данных VARCHAR».)
Естественно, что мы будем ожидать того же сообщения и при выполнении следующего оператора:
SELECT CAST(123456 AS VARCHAR(5))
Но нет. В результате мы получим символ «*» вместо сообщения об ошибке. Мы не беремся судить, с чем это связано, однако, однажды мы столкнулись с проблемой диагностики ошибки в коде, в котором впоследствии выполнялось обратное преобразование к числовому типу.
В нашем простейшем примере это будет выглядеть так:
SELECT CAST(CAST(123456 AS VARCHAR(5)) AS INT)
Вот тут-то мы и получаем ошибку:
Syntax error converting the varchar value '*' to a column of data type int.
(«Ошибка синтаксиса при преобразовании значения «*» к типу данных INT».)