Переменные в запросах. Переменные языка Transact-SQL Sql server переменные

Наверное, одним из первых вопросов, возникающих у начинающих программистов на T-SQL, это вопрос "А как получить выборку из таблицы, имя которой занесено в переменную?"
Т.к. в T-SQL нет возможности использовать в некоторых частях запроса значения переменных, то единственным доступным решением является использование динамического запроса. Идея очень проста: в специально определнной переменной "собирается" строка запроса, которая должна выполняться. Далее эта строка запускается на выполнение. Запуск можно осуществить двумя способами
- с помощью команды EXECUTE
- с помощью системной процедуры sp_executesql.

Выглядит это приблизительно так

DECLARE @SQL varchar (8000 ), @table_name varchar (10 ) SET @SQL = "SELECT * FROM " + @table_name exec (@SQL) --или exec sp_executesql @SQL Обычно динамические запроса формируются внутри хранимых процедур, в которых по входным параметром составляется конкретная строка выполнения.

I.Особенности динамического запроса
1. Динамический запрос ВСЕГДА выполняется В ТОМ-ЖЕ КОННЕКТЕ и КАК ОТДЕЛЬНЫЙ ПАКЕТ(batch). Другими словами при использовании такого запроса,
- вы ни имеете доступа к локальным переменным, объявленым до вызова динамического запроса (однако возможен доступ к cозданным ранее временным таблицам)
- локальные временые таблицы и переменные, созданные во время выполнения команды exec, будут недоступны в вызывающей процедуре, т.к. будут удалены по окончании пакета, в котором выполняется exec.

2. Динамический запрос ВСЕГДА выполняется с ПРАВАМИ ПОЛЬЗОВАТЕЛЯ, ВЫЗВАВШЕГО ПРОЦЕДУРУ, а не с правами владельца процедуры. Другими словами, если владельцем процедуры Procedure1 является User1, который имеет права к таблице Table1, то для пользователя User2 мало назначить права на выполнение процедуры Procedure1, если обращение в ней к таблице Table1 идет через динамический запрос. Придется давать ему соответствующие права и непосредственно для Table1.

3. Компиляция запроса происходят непосредственно перед его вызовом. Т.е. обо всех синтаксических ошибках вы узнаете только в этот момент.

II.Особенности использования команда exec
1. Команда exec поддерживает к качестве аргумента конкатенацю строк и/или переменных. НО не поддерживатеся конкатенация результатов выполнения функций, т.е. конструкции вида
exec ("SELECT * FROM " + LEFT (@TableName, 10 )) запрещены к использованию.
2. В команде нет входных/выходных параметров.

III.Особенности использования процедуры sp_executesql
1. Процедура НЕ поддерживает в качестве параметров конкатенацию строк и/или переменных.
2. Текст запроса должен быть либо переменной типа NVARCHAR/NCHAR, либо такого же типа стринговой константой.
3. Имеется возможность передачи параметров в выполняемый скрипт и получение выходных значений
Последнее явно в документации не описано, поэтому вот несколько примеров

В данном примере в динамический запрос передаются 4 переменные, три из которых являюся выходными

declare @var1 int , @var2 varchar (100 ), @var3 varchar (100 ), @var4 int declare @mysql nvarchar (4000 ) set @mysql = "set @var1 = @var1 + @var4; set @var2 = " "CCCC" "; set @var3 = @var3 + " "dddd" "" set @var1 = 0 set @var2 = "BBBB" set @var3 = "AAAA" set @var4 = 10 select @var1, @var2, @var3 exec sp_executesql @mysql, N"@var1 int out, @var2 varchar(100) out, @var3 varchar(100) out, @var4 int" , @var1 = @var1 out , @var2 = @var2 out , @var3 = @var3 out , @var4 = @var4 select @var1, @var2, @var3

В данном примере в динамическом запросе открывается курсор, который доступен в вызывающей процедуре через выходную переменную

USE pubs declare @cur cursor exec sp_executesql N"set @curvar= cursor local for select top 10 au_id, au_lname, au_fname from authors open @curvar" , N"@curvar cursor output " , @curvar=@cur output FETCH NEXT FROM @cur WHILE @@FETCH_STATUS = 0 BEGIN FETCH NEXT FROM @cur END

Резюме(более IMHO, чем обязательные требования)
Динамический запрос очень полезная и иногда просто незаменимая вещь, НО способы его реализации и конкретно через вызов в отдельном пакете с правами пользователя, вызвавшего процедуру, принижают его практическое МАССОВОЕ применение.

Цель работы – знакомство с основными приципами программирования в MS SQL Server средствами встроенного языка Transact SQL.

1. Знакомство с правилами обозначения синтаксиса команд в справочной системе MS SQL Server (утилита Books Online).

2. Изучение правил написания программ на Transact SQL.

3. Изучение правил построения идентификаторов, правил объявления переменных и их типов.

4. Изучение работы с циклами и ветвлениями.

5. Изучение работы с переменными типа Table и Cursor.

6. Проработка всех примеров, анализ результатов их выполнения.

7. Выполнение индивидуальных заданий по вариантам.

Пояснения к выполнению работы

Для освоения программирования используем пример базы данных c названием DB_Books, которая была создана в лабораторной работе №1.

При выполнении примеров и заданий обращайте внимание на соответствие названий БД, таблиц и других объектов проекта.

1. Специальные знаки и простейшие операторы в Transact SQL

Знак Назначение Знак Назначение
* Знак умножения » » В них заключают строковые значения, если SET QUOTED_IDENTIFIER OFF
- Знак вычитания ‘ ’ В них заключают строковые значения*
% Остаток от деления двух чисел <> Не равно
+ Знак сложения или конкатенации (объединение двух строк в одну) Аналог кавычек, в них можнозаключать названия идентификаторов, если в их названиях встречаются пробелы
= Знак равенства или сравнения !< Не менее чем
Меньше или равно !> Не более чем
>= Больше или равно > Больше
!= Не равно < Меньше
@ Ставится перед именем переменной . Разделяет родительские и подчиненные объекты
@@ Указывает на системные функции / Знак деления
Однострочный комментарий или комментарий с текущей позиции и до конца строки /* */ Многострочный комментарий

2. Идентификаторы

Идентификаторы – это имена объектов, на которые можно ссылаться в программе, написанной на языке Transact SQL. Первый символ может состоять из букв английского алфавита или «_», »@», »#». В качестве остальных символов идентификатора могут быть дополнительно использованы цифры и символ «$». Имя идентификатора не должно совпадать с зарезервированным словом (среда SQL Server Management Studio подсвечивает зарезервированные слова синим цветом).

Иногда в качестве идентификатора удобно использовать словосочетание. Можно воспользоваться заменой пробела на нижнее подчеркивание, а можно использовать ограничители идентификаторов - квадратные скобки или одинарные кавычки. Здесь надо обратить внимание на параметр QUOTED_IDENTIFIER.

Для ограничителей идентификаторов при установленном параметре

SET QUOTED_IDENTIFIER ON

можно использовать как квадратные скобки, так и одинарные кавычки, а строковые значения могут быть заключены только в одинарные кавычки (режим по умолчанию).

Если использовать установленный параметр в режиме

SET QUOTED_IDENTIFIER OFF

то в качестве ограничителей идентификаторов можно использовать только квадратные скобки, а строковые значения указываются в одинарных или двойных кавычках.

Переменные используются для сохранения промежуточных данных в хранимых процедурах и функциях. Все переменные считаются локальными. Имя переменной должно начинаться с @.

3. Объявление переменных

Синтаксис

DECLARE @имя_переменной1 тип_переменной, …, @имя_переменнойN тип_переменной

Если тип переменной предполагает указание размера, то используется следующий синтаксис для объявления переменных:

DECLARE @имя_переменной1 тип_переменной(размер) , …, @имя_переменнойN тип_переменной(размер)

Пример:

DECLARE @a INT , @b NUMERIC (10 , 2 ) DECLARE @str CHAR (20 )

4. Присвоение значений переменным и вывод значений на экран

Присвоение с помощью SET – обычное присвоение, синтаксис:

SET @имя_переменной = значение

Пример:

DECLARE @a INT , @b NUMERIC (10 , 2 ) SET @a = 20 SET @b = (@a+ @a) / 15 SELECT @b -- вывод на экран результата

Присвоение с помощью SELECT – помещение результата запроса в переменную. Если в результате выполнения запроса не будет возвращено ни одной строки, то значение переменной не меняется, т.е. остается старым.

Пример:

DECLARE @a INT SELECT @a = COUNT (* ) FROM Authors

Пример:

DECLARE @str CHAR (30 ) SELECT @str = name_author FROM Authors

В данном примере в переменную поместится последнее значение из результата запроса.

Пример:

DECLARE @a INT SET @a = (SELECT COUNT (* ) FROM Authors)

5. Работа с датой и временем

Оператор SET DATEFORMAT dmy | ymd | mdy задает порядок следования компонентов даты.

Пример:

SET DATEFORMAT dmy -- задает порядок следования компонентов даты. DECLARE @d DateTime -- объявляем переменную типа DateTime SET @d = "30.10.1821 0:00:00" SET @d = @d+ 1 -- прибавляем один день SELECT @d -- выводим значение переменной d в таблице

6. Создание временной таблицы через переменную типа TABLE

Объявляется через DECLARE с указанием в скобках столбцов таблицы, их типов, размеров, значений по умолчанию, а также индексов типа PRIMARY KEY или UNIQUE.

Пример:

/*Объявляем таблицу*/ DECLARE @mytable TABLE ( -- Объявление переменной типа TABLE id INT , -- Тип целых значений myname CHAR (20 ) DEFAULT "Введите имя" -- Тип значений и в ячейке выводится сообщение ) INSERT INTO @mytable(id) VALUES (1 ) -- Добавляем строку SELECT * FROM @mytable -- Выводим значение

Пример:

/*Объявляем таблицу*/ DECLARE @mytable TABLE ( id INT , myname CHAR (20 ) DEFAULT "Введите имя" ) INSERT @mytable SELECT Code_publish, City FROM Publishing_house SELECT * FROM @mytable

7. Преобразование типов переменных

Функция CAST возвращает значение, преобразованное к указанному типу:

CAST (@переменная или значение AS требуемый_тип_данных)

Пример:

DECLARE @d DateTime, @str CHAR (20 ) -- объявляем переменные типа DateTime и char SET @d = "31.01.2005 13:23:15" -- устанавливаем значение переменной d SET @str = CAST (@d AS CHAR (20 ) ) -- устанавливаем значение str, приводим к формату char SELECT @str -- выводит значение переменной

Функция CONVERT возвращает значение, преобразованное к указанному типу по заданному формату. Изучить дополнительно, по желанию.

8. Операторские скобки

BEGIN /* В них нельзя помещать команды, изменяющие структуры объектов БД. Операторские скобки должны содержать хотя бы один оператор. Требуются для конструкций поливариантных ветвлений, условных и циклических конструкций */ END

9. Условная конструкция IF

Синтаксис:

IF условие Набор операторов1 ELSE Набор операторов2

Пример:

DECLARE @a INT DECLARE @str CHAR (40 ) -- объявляет переменную типа CHAR SET @a = (SELECT COUNT (name_author) FROM Authors) -- устанавливает значение a, равное количеству -- записей в столбце name_author IF @a > 10 BEGIN SET @str = "Количество авторов больше 10" -- если а>10, то выводится сообщение "Количество авторов больше 10" SELECT @str END ELSE BEGIN SET @str = " Количество авторов = " + str(@a) -- иначе количество авторов равно значению переменной а SELECT @str -- вывод значения переменной str END

10. Цикл WHILE

Синтаксис:

WHILE Условие Набор операторов1 BREAK Набор опреторов2 CONTINUE

Конструкции BREAK и CONTINUE являются необязательными. Цикл можно принудительно остановить, если в его теле выполнить команду BREAK. Если же нужно начать цикл заново, не дожидаясь выполнения всех команд в теле, необходимо выполнить команду CONTINUE.

Пример:

DECLARE @a INT -- объявляет переменную типа INT SET @a = 1 -- устанавливает значение а =1 WHILE @a < 100 -- цикл работает пока значение переменной а<100 BEGIN PRINT @a IF (@a> 40 ) AND (@a< 50 ) -- если значение переменной а>40 и a <50 BREAK -- выход и выполнение 1-й команды за циклом ELSE -- иначе SET @a = @a+ rand() * 10 -- устанавливаем значение а равное переменной а + случайное число из диапазона (0, 1), -- умноженное на 10 CONTINUE -- запускаем цикл заново, не дожидаясь выполнения всех команд в теле END PRINT @a -- вывод на экран значения переменной

11. Объявление курсора

CURSOR – это набор строк, являющийся результатом выполнения запроса. В один момент времени доступна лишь одна строка (текущая), по курсору можно передвигаться и получать доступ к элементарным данным. При объявлении курсора создается временная копия данных, которая сохраняется в БД tempdb.

Динамический курсор – данные в курсоре могут быть изменены.

Статический курсор – данные в курсоре не меняются.

Стандартный способ объявления курсора, синтаксис в обозначениях MS SQL Server:

DECLARE cursor_name [ INSENSITIVE ] [ SCROLL ] CURSOR FOR select_statement [ FOR { READ ONLY | UPDATE [ OF column_name [ ,... n ] ] } ]

Примеры объявления курсоров

1. Объявляем курсор с названием MyCursor1, который содержит всю информацию об авторах, двигаться по нему можно только от первой записи вниз до последней. Курсор является динамическим.

DECLARE MyCursor1 CURSOR FOR (SELECT * FROM Authors)

2. Объявляем курсор с названием MyCursor1, который содержит всю информацию об авторах, двигаться по нему можно только от первой записи вниз до последней. Курсор является статическим.

DECLARE MyCursor1 INSENSITIVE CURSOR FOR (SELECT * FROM Authors)

3. Объявляем курсор с названием MyCursor1, который содержит всю информацию об авторах, двигаться по нему можно в любом направлении. Курсор является динамическим.

DECLARE MyCursor1 SCROLL CURSOR FOR (SELECT * FROM Authors)

4. Объявляем курсор с названием MyCursor1, который содержит всю информацию об авторах, двигаться по нему можно в любом направлении. Курсор является статическим.

DECLARE MyCursor1 INSENSITIVE SCROLL CURSOR FOR (SELECT * FROM Authors)

5. Объявляем курсор с названием MyCursor1, который содержит всю информацию об авторах, двигаться по нему можно только от первой записи вниз до последней. Курсор является динамическим. Данные доступны только для чтения.

DECLARE MyCursor1 CURSOR FOR (SELECT * FROM Authors) FOR READ ONLY

6. Объявляем курсор с названием MyCursor1, который содержит всю информацию об авторах, двигаться по нему можно только от первой записи вниз до последней. Курсор является динамическим. Данные курсора можно менять.

DECLARE MyCursor1 CURSOR FOR (SELECT * FROM Authors) FOR UPDATE

12. Операторы для работы с курсором

Прежде чем обратиться к данным курсора, его нужно после объявления открыть.

Синтаксис оператора OPEN в обозначениях MS SQL Server:

OPEN { { [ GLOBAL ] cursor_name} | cursor_variable_name }

Пример:

После прекращения работы с курсором, его нужно закрыть. Курсор остается доступным для последующего использования в рамках процедуры или триггера, в котором он создан.

Синтаксис оператора CLOSE в обозначенияхMS SQL Server:

CLOSE { { [ GLOBAL ] cursor_name} | cursor_variable_name}

Пример:

DECLARE MyCursor1 CURSOR FOR (SELECT * FROM Authors) OPEN MyCursor1 CLOSE MyCursor1

Если курсором больше не будут пользоваться, то его необходимо уничтожить и освободить переменную.

Синтаксис оператора DEALLOCATE в обозначениях MS SQL Server:

DEALLOCATE { { [ GLOBAL ] cursor_name} | @cursor_variable_name }

Пример:

DECLARE MyCursor1 CURSOR FOR (SELECT * FROM Authors) OPEN MyCursor1 --здесь операторы работы с курсором CLOSE MyCursor1 DEALLOCATE MyCursor1

FETCH – оператор движения по записям курсора и извлечения данных текущей записи в указанные переменные. Синтаксис оператора FETCH в обозначениях MS SQL Server:

FETCH [ [ NEXT | PRIOR | FIRST | LAST | ABSOLUTE { n | @nvar } | RELATIVE { n | @nvar } ] FROM ] { { [ GLOBAL ] cursor_name} | @cursor_variable_name } [ INTO @variable_name [ 1 ,..., n ] ]

Пример:

DECLARE MyCursor1 SCROLL CURSOR FOR (SELECT * FROM Authors) DECLARE @i BIGINT , @s CHAR (20 ) , @d smalldatetime OPEN MyCursor1 FETCH FIRST FROM MyCursor1 INTO @i, @s, @d PRINT @i PRINT @s PRINT @d CLOSE MyCursor1 DEALLOCATE MyCursor1

@@FETCH_STATUS – данная функция определяет признак конца или начала текущего курсора. Функция принимает одно из следующих значений:

    1 – попытка выйти за пределы первой записи вверх (в никуда);

    2 – попытка выйти за пределы последней записи вниз(в никуда).

Пример:

DECLARE MyCursor1 SCROLL CURSOR FOR (SELECT * FROM Authors) DECLARE @i BIGINT , @s CHAR (20 ) , @d smalldatetime -- объявляем переменные OPEN MyCursor1 -- открываем MyCursor1 FETCH FIRST FROM MyCursor1 INTO @i, @s, @d -- устанавливаем курсор на первую строку таблицы Authors WHILE @@FETCH_STATUS = 0 -- пока находимся в пределах таблицы BEGIN FETCH NEXT FROM MyCursor1 INTO @i, @s, @d -- записываем данные из текущей строки в переменные PRINT @i -- выводим code_author в переменную i PRINT @s -- выводим name_author в переменную s PRINT @d -- выводим birthday в переменную d END CLOSE MyCursor1 -- закрываем курсор DEALLOCATE MyCursor1 -- освобождаем память

13. Пример создания и запуска процедуры с курсором

Пример создания процедуры USE DB_book; GO IF OBJECT_ID ("Book" , "P" ) IS NOT NULL -- если уже существует объект (процедура) с именем "Book", DROP PROCEDURE Book; -- удаляем этот объект GO CREATE PROCEDURE Book -- создаем процедуру Book, возвращающую значение переменной cur1 @cur1 CURSOR VARYING OUTPUT -- параметры курсора в хранимой процедуре обязательно должны быть -- CURSOR VARYING OUTPUT AS -- далее - тело процедуры SET @cur1 = CURSOR FOR -- объявляем переменную типа курсор SELECT name_author FROM Authors; -- выводим в курсор значения записи name_author OPEN @cur1; -- открываем переменную GO --пример запуска процедуры с курсором USE DB_book; GO DECLARE @MyCursor CURSOR; -- объявляем курсор DECLARE @a CHAR (30 ) ; -- объявляем переменную @a EXEC book @cur1 = @MyCursor OUTPUT; -- запускаем процедуру и выводим возвращаемые значения -- в объявленный курсор FETCH NEXT FROM @MyCursor INTO @a; -- устанавливаем курсор на первую запись таблицы и выводим -- значение в переменную @a WHILE (@@FETCH_STATUS = 0 ) -- пробегаем по всем строкам таблицы BEGIN PRINT @a; -- выводим на экран значение переменной @a FETCH NEXT FROM @MyCursor INTO @a; -- устанавливаем курсор на следующую запись таблицы и выводим -- значение в переменную @a END ; CLOSE @MyCursor; -- закрываем курсор DEALLOCATE @MyCursor; -- освобождаем память GO

14. Встроенные функции

Встроенные функции, имеющиеся в распоряжении пользователей при работе с SQL, можно условно разделить на следующие группы:

    математические функции;

    строковые функции;

    функции для работы с датой и временем;

    функции конфигурирования;

    функции системы безопасности;

    функции управления метаданными;

    статистические функции.

Краткий обзор строковых функций

Название функций
ASCII Возвращает код ASCII левого символа строки
CHAR По коду ASCII возвращает символ
CHARINDEX Определяет порядковый номер символа, с которого начинается вхождение подстроки в строку
DIFFERENCE Возвращает показатель совпадения строк
LEFT Возвращает указанное число символов с начала строки
LEN Возвращает длину строки
LOWER
LTRIM Удаляет пробелы в начале строки
NCHAR Возвращает по коду символ Unicode
PATINDEX Выполняет поиск подстроки в строке по указанному шаблону
REPLACE Заменяет вхождения подстроки на указанное значение
QUOTENAME Конвертирует строку в формат Unicode
REPLICATE Выполняет тиражирование строки определенное число раз
REVERSE Возвращает строку, символы которой записаны в обратном порядке
RIGHT Возвращает указанное число символов с конца строки
RTRIM Удаляет пробелы в конце строки
SOUNDEX Возвращает код звучания строки
SPACE Возвращает указанное число пробелов
STR Выполняет конвертирование значения числового типа в символьный формат
STUFF Удаляет указанное число символов, заменяя новой подстрокой
SUBSTRING Возвращает для строки подстроку указанной длины с заданного символа
UNICODE Возвращает Unicode-код левого символа строки
UPPER Переводит все символы строки в верхний регистр

Использование функций для работы с числами

Краткий обзор математических функций

Название функций Действие, выполняемое функцией
ABS Вычисляет абсолютное значение числа
ACOS Вычисляет арккосинус
ASIN Вычисляет арксинус
ATAN Вычисляет арктангенс
ATN2 Вычисляет арктангенс с учетом квадратов
CEILING Выполняет округление вверх
COS Вычисляет косинус угла
COT Переводит все символы строки в нижний регистр
DEGREES Преобразует значение угла из радиан в градусы
EXP Возвращает экспоненту
FLOOR Выполняет округление вниз
LOG Вычисляет натуральный логарифм
LOG10 Вычисляет десятичный логарифм
PI Возвращает значение «пи»
POWER Возводит число в степень
RADIANS Преобразует значение угла из градуса в радианы
RAND Возвращает случайное число
ROUND Выполняет округление с заданной точностью
SIGN Определяет знак числа
SIN Вычисляет синус угла
SQUARE Выполняет возведение числа в квадрат
SQRT Извлекает квадратный корень
TAN Возвращает тангенс угла

Краткий обзор основных функций для работы с датой и временем

DATEADD Добавляет к дате указанное значение дней, месяцев, часов и т.д.
DATEDIFF Возвращает разницу между указанными частями двух дат
DATENAME Выделяет из даты указанную часть и возвращает ее в символьном формате
DATEPART Выделяет из даты указанную часть и возвращает ее в числовом формате
DAY Возвращает число из указанной даты
GETDATE Возвращает текущее системное время
ISDATE Проверяет правильность выражения на соответствие одному из возможных форматов ввода даты
MONTH Возвращает значение месяца из указанной даты
YEAR Возвращает значение года из указанной даты
MINUTE Возвращает значение минут из указанной даты/времени
HOUR Возвращает значение часов из указанной даты/времени
SECOND Возвращает значение секунд из указанной даты/времени

Варианты заданий к лабораторной работе №4

Общие сведения

Для получения более подробной информации о работе тех или иных операторов или функций можно запустить утилиту Books Online из состава MS SQL Server и в разделе «Указатель» набрать искомый ключевой элемент.

Специальные знаки и простейшие операторы в Transact SQL

Пример. Проверить работу описанной установки SET QUOTED_IDENTIFIER

Напишем следующий запрос (объявим строковую переменную и значение её заключим в двойные кавычки)

DECLARE @A CHAR (30 ) SET @A = "ПРИВЕТ"

Если предварительно было установлено SET QUOTED_IDENTIFIER ON , то запрос завершится ошибкой. Чтобы запрос сработал нужно выставить SET QUOTED_IDENTIFIER OFF:

SET QUOTED_IDENTIFIER OFF DECLARE @A CHAR (30 ) SET @A = "ПРИВЕТ"

Задание .

1. Проверить работу описанной установки SET DATEFORMAT.

Объявление переменных

Пример. Объявить переменную Perem1 типа денежный, а переменную Perem2 типа число с целой частью равной 8 и дробной частью равной 2.

DECLARE @a MONEY, @b NUMERIC (10 , 2 ) DECLARE @str CHAR (20 )

Money - тип данных, представляющие денежные (валютные) значения. Диапазон От -922 337 203 685 477,5808 до 922 337 203 685 477,5807 (8 байт). Numeric(n,m) - тип данных с фиксированной запятой (n - общее число десятичных разрядов, m - количество знаков после запятой).

Задания.

2. Объявить переменную Perem1 типа строка длиной 100, а переменную Perem2 типа длинное целое.

3. Объявить переменную Perem1 типа динамическая строка с максимальной длиной 1000, а переменную Perem2 типа целое число.

4. Объявить переменную Perem1 типа строка длиной 30, а переменную Perem2 типа число с целой частью равной 10 и дробной частью равной 3.

5. Объявить переменную Perem1 типа дата/ время, а переменную Perem2 типа число в диапазоне от 0 до 255.

Присвоение значений переменным и вывод значений на экран

Сочетание ключевых слов SET и SELECT

Работа с датой и временем

14. Определить переменную Date1 типа дата/время. Присвоить ей значение даты 31.12.2006 в формате dd.mm.yyyy.

15. Определить переменную Date1 типа дата/время. Присвоить ей значение даты 31.12.2006 в формате mm.dd.yyyy.

16. Определить переменную Date1 типа дата/время. Присвоить ей значение даты 31.12.2006 в формате yyyy.mm.dd. Создание временной таблицы через переменную типа TABLE

Использование локальных переменных

Пример. Создать локальную таблицу с названием TEMP и полями типа дата/время, длинное целое, строка. Добавить в нее две записи с данными и вывести результат на экран.

DECLARE @temp TABLE ( id INT , DATE DATETIME, num BIGINT DEFAULT 0 , myname CHAR (50 ) DEFAULT "Введите имя" ) INSERT INTO @temp(id, DATE ) VALUES (2 , "25.11.2001" ) INSERT INTO @temp(id, DATE , myname) VALUES (3 , "26.11.2001" , "Кирилл" ) SELECT * FROM @temp

Задания.

17. Создать локальную таблицу с названием TEMP и полями типа длинное целое, строка и значением по умолчанию «введите что-нибудь», денежный. Добавить в нее две записи с данными и вывести результат на экран.

18. Создать локальную таблицу с названием TEMP и полями типа целое, динамическая строка, бит со значением по умолчанию «1». Добавить в нее две записи с данными и вывести результат на экран.

19. Создать локальную таблицу с названием TEMP и полями типа дата/время, длинное целое, строка. Добавить в нее две записи с данными и вывести результат на экран.

20. Создать локальную таблицу с названием TEMP и полями типа дата/время, длинное целое с автонаращиванием, динамическая строка. Добавить в нее две записи с данными и вывести результат на экран.

Преобразование типов переменных

Пример. Объявить переменные типа BIT, NVARCHAR, DATETIME. Присвоить значения, соответствующие типам. Выполнить преобразование переменных типа BIT, NVARCHAR, DATETIME в FLOAT, INT, BIGINT соответственно и вывести результат на экран.

DECLARE @d BIT, @str NVARCHAR(30 ) , @dat DATETIME SET @d = "True" SET @dat = "31.01.2005 13:23:15" SET @str = "1111111111" SELECT CAST (@d AS FLOAT ) AS float1 SELECT CAST (@dat AS BIGINT ) AS bigint1 SELECT CAST (@str AS INT ) AS int1

Задания.

21. Объявить переменные типа FLOAT, CHAR, TINYINT. Присвоить значения, соответствующие типам. Выполнить преобразование переменных типа FLOAT, CHAR, TINYINT в INT, DATETIME, BIT соответственно и вывести результат на экран.

22. Объявить переменные типа INT, DATETIME, BIT. Присвоить значения, соответствующие типам. Выполнить преобразование переменных типа INT, DATETIME, BIT в FLOAT, CHAR, TINYINT соответственно и вывести результат на экран.

23. Объявить переменные типа NUMERIC, VARCHAR, DATETIME. Присвоить значения, соответствующие типам. Выполнить преобразование переменных типа NUMERIC, VARCHAR, DATETIME в FLOAT, CHAR, BIGINT соответственно и вывести результат на экран.

Условная конструкция IF

Задания.

24. Подсчитать количество поставщиков в таблице Deliveries. Если их в таблице от 2 до 5, то ничего не сообщать, в противном случае вывести сообщение вида «В таблице … поставщиков» (вместо многоточия поставить точное количество поставщиков).

25. Подсчитать сумму закупок книг в таблице покупок. Если полученная сумма в диапозоне от 1000 до 5000, то ничего не сообщать, в противном случае вывести сообщение вида «Сумма закупок = …» (вместо многоточия поставить точную сумму).

26. Подсчитать среднюю стоимость закупки книг в таблице покупок. Если полученная стоимость в диапозоне от 1000 до 5000, то ничего не сообщать, в противном случае вывести сообщение вида «Средняя стоимость закупки = …» (вместо многоточия поставить точную среднюю стоимость).

27. Определить минимальную стоимость закупки книг в таблице покупок. Если полученная стоимость в диапозоне от 200 до 300, то ничего не сообщать, в противном случае вывести сообщение вида «Минимальная стоимость закупки = …» (вместо многоточия поставить точную стоимость).

Цикл WHILE

Пример. Определить количество записей в таблице Authors. Пока записей меньше 100, делать в цикле добавление записи в таблицу с автоматическим наращиванием значения ключевого поля, а вместо имени автора ставить значение „Автор не известен“.

USE DB_book DECLARE @a INT DECLARE @b INT SET @a= (SELECT COUNT (Authors. Code_author) FROM authors) SET @b= @a+ 1 WHILE @b < 100 BEGIN INSERT INTO Authors(code_author, name_author) VALUES (@b, "Автор неизвестен" ) SET @b= @b+ 1 -- цикл работает пока значение переменной b<100 END SELECT * FROM Authors

Задания.

28. Определить количество записей в таблице издательств. Пока записей меньше 20, делать в цикле добавление записи в таблицу с автоматическим наращиванием значения ключевого поля, а вместо названия издательства ставить значение „не известно“.

29. Определить количество записей в таблице поставщиков. Пока записей меньше 17, делать в цикле добавление записи в таблицу с автоматическим наращиванием значения ключевого поля, а вместо названия поставщика ставить значение „не известен“.

Объявление курсора

Пример. Создать статический курсор по данным таблицы Books с полями Code_book, Title_book.

DECLARE MyCursor1 INSENSITIVE SCROLL CURSOR FOR (SELECT Code_book, Title_book FROM Books) OPEN MyCursor1 FETCH FIRST FROM MyCursor1 CLOSE MyCursor1 DEALLOCATE MyCursor1

Задания.

30. Создать динамический курсор по данным таблицы поставщиков (таблица Deliveries) с полями Name_delivery, Name_company.

31. Создать статический курсор по данным таблицы Books и Authors с полями Code_book, Title_book, Name_author.

32. Создать статический курсор по данным таблицы Books и Publishing_house с полями Code_book, Title_book, Publish.

Операторы для работы с курсором

Пример. Создать динамический курсор для чтения по данным таблицы Deliveries с полями Code_delivery, Name_delivery. Вывести данные 3-й записи.

DECLARE MyCursor1 SCROLL CURSOR FOR (SELECT Code_delivery, Name_delivery FROM Deliveries) DECLARE @i BIGINT , @s CHAR (30 ) OPEN MyCursor1 FETCH FIRST FROM MyCursor1 INTO @i, @s FETCH NEXT FROM MyCursor1 INTO @i, @s FETCH NEXT FROM MyCursor1 INTO @i, @s PRINT @i PRINT @s CLOSE MyCursor1 DEALLOCATE MyCursor1

Задания.

33. Сделать текущей БД db_books. Поместить в курсор данные таблицы Purchases. Перебрать все записи таблицы Purchases. Просуммировать значения произведений полей Cost и Amount и результат сохранить в переменной Sum_table, которую после суммирования вывести на экран. Закрыть и удалить из памяти курсор.

34. Объявить статический курсор по данным таблиц Authors и Books. Вывести данные 5-й записи.

Использование функций для работы со строковыми переменными

Базовый текст дан в отдельном файле по вариантам. Для выполнения этого блока заданий в начале программы, которую вы создаете, объявите переменную типа varchar и присвойте ей в качестве значения строку с любым базовым текстом, который будет анализироваться и/или справляться в заданиях.

Пример. Удалить в тексте лишние пробелы. Лишними считаются те, которые идут непосредственно за пробелом. Подсчитать количество исправлений.

DECLARE @text VARCHAR (100 ) -- Объявляем переменную типа динамической строки длинною до 100 символов DECLARE @i INT -- Счетчик цикла DECLARE @c CHAR (1 ) -- Отдельный символ строки DECLARE @ctemp CHAR (1 ) -- Предыдущий по отношению к @c символ строки DECLARE @a INT -- Количество лишних пробелов SET @a= 0 ; SET @text = " съешь еще этих мягких французских булок с изюмом " SET @ctemp = SUBSTRING (@text, 1 , 1 ) -- Полагаем @ctemp равным первому символу строки SET @i = 2 While @i < len (@text) + 1 BEGIN SET @c = SUBSTRING (@text, @i, 1 ) -- Если два соседние символа - пробелы, удаляем один из них IF ((@ctemp= " " ) AND (@c= " " ) ) BEGIN SET @text = (SELECT stuff (@text, @i- 1 , 1 , "" ) ) SET @a= @a+ 1 END SET @ctemp = @c SET @i= @i+ 1 END SELECT @text SELECT @a

37. По правилам оформления машинописных текстов перед знаками.,!?:; пробелы не ставятся, но обязательно ставятся после этих знаков. Удалите лишние пробелы. Подсчитать количество исправлений.

38. По правилам оформления машинописных текстов перед знаками.,!?:; пробелы не ставятся, но обязательно ставятся после этих знаков. Расставьте недостающие пробелы. Подсчитать количество исправлений.

39. Найти из исходного текста второе предложение и вернуть его в переменную Perem, а также вывести на экран весь исходный текст и найденное предложение.

40. Удалить из базового текста 2, 4, 6, 8 слова.

41. Удалить из базового текста 3, 5, 7, 10 слова.

42. Вставить в базовый текст вместо букв «а» - «АА».

43. Вставить в базовый текст вместо букв «е» и «о» - «ББ». 44. Поменять местами первое и последнее слова в базовом тексте.

Использование функций для работы с типом дата/время

Пример. Вывести на экран название текущего месяца и текущее время. Записать в таблицу Purchases в поле Date_order одинаковую дату поступления, которая равна 12.03.2000.

SELECT DATENAME(MONTH , GETDATE() ) + ", " + CAST (DATEPART(HOUR , GETDATE() ) AS CHAR (4 ) ) + ":" + CAST (DATEPART(MINUTE , GETDATE() ) AS CHAR (4 ) ) + ":" + CAST (DATEPART(SECOND , GETDATE() ) AS CHAR (4 ) ) UPDATE PURCHASES SET DATE_ORDER = "12.03.2000"

Задания.

45. Разобрать на отдельные составляющие текущую дату и время и вывести значения на экран в следующем порядке (вместо многоточий): «Сегодня: День = …, Месяц = …, Год = …, Часов = …, Минут = …, Секунд= …»

46. В исходный текст, сохраненный в переменной Perem, после слова » время » вставить текущее время. Результат сохранить в той же переменной Perem и вывести на экран.

В Microsoft SQL Server есть особый тип данных TABLE, на основе которого мы можем создавать табличные переменные , для того чтобы использовать их в своих инструкциях и процедурах, и сегодня мы с Вами рассмотрим эти переменные, узнаем, как они объявляются и какие у этих переменных особенности.

Описание табличных переменных MS SQL Server

Табличные переменные – это переменные с особым типом данных TABLE, которые используются для временного хранения результирующего набора данных в виде строк таблицы. Появились они еще в 2005 версии SQL сервера. Использовать такие переменные можно и в хранимых процедурах, и в функциях, и в триггерах, и в обычных SQL пакетах. Создаются табличные переменные так же, как и обычные переменные, путем их объявления инструкцией DECLARE.

Переменные такого типа предназначены в качестве альтернативы временным таблицам. Если говорить о том, что лучше использовать табличные переменные или временные таблицы, то однозначного ответа нет, у табличных переменных есть и плюсы, и минусы. Например, лично мне нравиться использовать табличные переменные, потому что их удобно создавать (т.е. объявлять ) и не нужно думать об их удалении или очищение в конце инструкции, так как они автоматически очищаются (как и обычные переменные ). Но при этом табличные переменные лучше использовать только тогда, когда Вы собираетесь хранить в них небольшой объём данных, в противном случае рекомендуется использовать временные таблицы.

Преимущества табличных переменных в Microsoft SQL Server

  • Табличные переменные ведут себя как локальные переменные. Они имеют точно определенную область применения;
  • Табличные переменные автоматически очищаются в конце инструкции, где они были определены;
  • При использовании табличных переменных в хранимых процедурах повторные компиляции происходят реже, чем при использовании временных таблиц;
  • Транзакции с использованием переменных TABLE продолжаются только во время процесса обновления соответствующей переменной. За счет этого табличные переменные реже подвергаются блокировке и требуют меньше ресурсов для ведения журналов регистрации.

Недостатки табличных переменных в MS SQL Server

  • Запросы, которые изменяют переменные TABLE, не создают параллельных планов выполнения запроса;
  • Переменные TABLE не имеют статистики распределения и не запускают повторных компиляций, поэтому рекомендуется использовать их для небольшого количества строк;
  • Табличные переменные нельзя изменить после их создания;
  • Табличные переменные нельзя создавать путем инструкции SELECT INTO;
  • Переменные TABLE не изменяются в случае откатов транзакций, так как имеют ограниченную область действия и не являются частью постоянных баз данных.

Примеры использования табличных переменных в Microsoft SQL Server

Сейчас давайте перейдем к практике, и для начала хотелось бы отметить, что в качестве сервера у меня выступает Microsoft SQL Server 2016 Express , другими словами все запросы ниже запускались на данной версии СУБД.

Сначала давайте создадим тестовую таблицу и заполним ее тестовыми данными, для того чтобы посмотреть, как можно использовать табличные переменные вместе с обычными таблицами.

CREATE TABLE TestTable(ProductId INT IDENTITY(1,1) NOT NULL, ProductName VARCHAR(50) NULL CONSTRAINT PK_TestTable PRIMARY KEY CLUSTERED (ProductId ASC)) GO INSERT INTO TestTable (ProductName) VALUES ("Компьютер"), ("Монитор"), ("Принтер") GO SELECT * FROM TestTable


С помощью инструкции CREATE TABLE я создал таблицу TestTable, затем для добавления данных в таблицу я использовал инструкцию INSERT совместно с конструктором табличных значений VALUES , затем с помощью SELECT сделал выборку из только что созданной таблицы.

Объявление табличной переменной и ее использование

В данном примере мы объявим табличную переменную, добавим в нее данных, и сделаем выборку из двух таблиц (табличной переменной и обычной таблицы ) с объединением.

Объявление табличной переменной DECLARE @TableVar TABLE(ProductId INT NOT NULL, Price MONEY NULL); --Добавление данных в табличную переменную INSERT INTO @TableVar (ProductId, Price) VALUES (1, 500), (2, 300), (3, 200) --Использование табличной переменной с объединением данных SELECT TTable.ProductId, TTable.ProductName, TVar.Price FROM @TableVar TVar LEFT JOIN TestTable TTable ON TVar.ProductId = TTable.ProductId


Создание табличной переменной с первичным ключом, ограничением UNIQUE и с некластеризованным индексом

В данном примере показано, как можно создавать первичный ключ, ограничения UNIQUE и некластеризованные индексы для табличных переменных. Возможность создания некластеризованного индекса появилась, начиная с версии Microsoft SQL Server 2014.

Объявление табличной переменной DECLARE @TableVar TABLE(ProductId INT NOT NULL PRIMARY KEY, --Первичный ключ ProductName VARCHAR(50) NOT NULL, Price MONEY NOT NULL, UNIQUE (ProductName, Price), --Ограничение INDEX IX_TableVar NONCLUSTERED (Price) --Некластеризованный индекс); --Добавление данных в табличную переменную INSERT INTO @TableVar (ProductId, ProductName, Price) VALUES (1, "Компьютер", 500), (2, "Монитор", 300), (3, "Принтер", 200); --Выборка данных SELECT ProductName FROM @TableVar WHERE Price > 200


На этом мой рассказ о табличных переменных закончен, если Вы хотите детально изучить язык T-SQL, то рекомендую почитать мою книгу «Путь программиста T-SQL », надеюсь, материал был Вам полезен, пока!

Инструкция SET присваивает значение переменной времени выполнения. Эти переменные могут быть системными переменными, специфичными для платформы, или пользовательскими переменными.

Ключевые слова

переменная

Обозначает системную или пользовательскую переменную.

значение

Обозначает строковое или числовое значение, соответствующее системной или пользовательской переменной.

Общие правила

Значения переменных устанавливаются на время сеанса. Значения, присвоенные переменной, должны соответствовать типу данных этой переменной. Например, вы не можете присвоить строковое значение переменной, которая объявлена с числовым типом данных. Команда, с помощью которой переменная создается, на разных платформах разная. Например, в DB2, Oracle и SQL Server используется инструкция DECLARE, в которой объявляется имя и тип переменной, однако на других платформах могут использоваться другие способы создания переменных.

Значение, которое присваивается переменной, не обязательно должно быть константой. Это может быть динамически генерируемое значение, создаваемое на основе подзапроса. Например, мы можем присвоить переменной emp_id_var максимальное значение идентификатора сотрудника (emp_id)|.

DECLARE emp_icLvar CHAR(5) SET empty var=(SELECT MAX(emp_id) FROM employees WHERE type="F")

В этом примере type F обозначает, что сотрудник работает полный день (full-time) и состоит на окладе.

Инструкция SET очень легко переносится с платформы на платформу. Только в Oracle используется несколько другая схема присвоения значения переменной. В следующем примере мы объявим в SQL Server переменную с именем emp_id_var и присвоим ей значение.

DECLARE emp_id var CHAR(5) SET emp_id_var="67888";

А теперь мы выполним ту же самую операцию для сервера Oracle.

DECLARE emp_id_var CHAR(5); emp_id_var:= "67888";

DB2

Платформа DB2 поддерживает базовую форму инструкции SET для присвоения значений локальным переменным, выходным параметрам или особым регистрам. В одной инструкции SET можно присваивать сразу несколько значений. Также эта инструкция позволяет присваивать значения столбцам базовой таблицы в триггере. Нельзя присвоить значения в одной инструкции двум типам переменных.

SET переменная={значение | NULL | DEFAULT} [, …]

Синтаксические элементы в DB2 следующие.

переменная

Указывается целевая переменная. Переменные SQL должны быть объявлены до использования. Переменная также может обозначать столбец базовой таблицы триггера.

значение

Указывается значение переменной в соответствии с ее типом данных. При присвоении значений столбцам в триггере вы также можете использовать ссылки на корреляционные имена OLD и NEW. За дополнительной информацией об этом обращайтесь к подразделу, посвященному DB2, раздела «Инструкция CREATE/ ALTER TRIGGER)).

Столбцу и переменной, которые могут принимать значения NULL, присваивается значение NULL.

Столбцам, которые создавались с указанием предложения WITH DEFAULT или IDENTITY, присваивается значение по умолчанию. Это предложение также присваивает пустое значение (NULL) тем столбцам, которые принимают пустые значения и при этом не определены с предложениями DEFAULTтя IDENTITY. Присвоим значение одной переменной.

SET new var.order_qty=125;

Если вы присваиваете значения в одной инструкции сразу нескольким переменным, то количество переменных слева от знака равенства должно в точности соответствовать количеству значений справа. Присвоим значения нескольким переменным.

SET new_var. order_qty=125, new_.va г. discount =

При использовании такого варианта, как SET переменная=SELECT значения результирующего набора инструкции SELECT должны в точности соответствовать переменным по количеству, положению и типу данных. Если инструкция SELECT не возвращает никаких значений, то переменным присваиваются значения NULL. Также для присвоения значений нескольким переменным в одной инструкции вы можете использовать инструкцию SELECT…INTO.

MySQL

Ключевое слово SET имеет в MySQL несколько способов использования. Во-первых, SET - это тип данных MySQL, в котором может быть несколько значений, разделенных запятыми. (За информацией об этой области применения обращайтесь к главе 2, раздел «Типы данных MySQL».) Кроме того, инструкция SET может присваивать значения пользовательской переменной. Здесь описывается именно этот способ применения. Синтаксис следующий:

SET переменная - значение […]

При присвоении в одной инструкции значений нескольким переменным эти значения отделяются друг от друга запятыми.

SET new_var.order_.aty - 125. new_var. discount - 4;

Кроме того, MySQL позволяет использовать инструкцию SELECT для присвоения значений переменным точно так же, как это описывается в разделе, посвященном стандарту ANSI. Однако у метода с использованием инструкции SELECT есть несколько слабых мест. Главная проблема состоит в том, что значения не присваиваются и инструкции SELECT немедленно. Таким образом, в следующем примере:

SELECT (_>new_var - row_id) AS а, (@new_var + 3) AS b FROM Lable_name;

переменная @new_var не получит нового значения row id + 3. Сохранится то значение, которое она имела в начале инструкции. Поэтому хорошей практикой является присвоение переменной только одного значения за раз.

Oracle

Предложение SET как метод присваивания значения переменным в Oracle не поддерживается. Вместо этого пользовательским переменным значения присваиваются при помощи оператора присваивания:=. Базовый синтаксис следующий.

PostgreSQL

В PostgreSQL команда SET используется для присваивания значения переменной во время выполнения.

SET переменная{ТО | -} {значение | DEFAULT}

Переменной во время выполнения можно присвоить строковое постоянное значение. При использовании ключевого слова DEFAULT переменной времени выполнения присваивается значение по умолчанию. Платформа PostgreSQL 7.2 поддерживает следующие переменные.

CLIENT ENCODING NAMES

Устанавливается мультибайтовая кодировка для клиентских систем PostgreSQL, скомпонованных с мультибайтовой поддержкой.

DATESTYLE

Устанавливается стиль, используемый для отображения даты и времени. Поддерживаются следующие стили.

Дата и время отображаются в формате ГПТ-ММ-ДД ЧЧ:ММ:СС (заданный по умолчанию стиль ISO 8601).

Дата и время отображаются в стиле Oracle/Ingres, а не в том стиле, который предписывается стандартом ANSI SQL.

PostgreSQL

Дата и время отображаются в длинном формате PostgreSQL, но не длиннее, чем задано по умолчанию.

Дата и время отображаются в виде ДД.ММ.ГГГГ. Вы можете уточнять стили SQL и Postgresql, используя ключевые слова European, US и NonEuropean, которые придают датам форматы дд/мм/гггг, мм/дд/гггг и мм/дд/гггг соответственно. Например: SETDATESTYLE=SQL, European.

Устанавливается начальное значение для внутреннего генератора случайных чисел. Значение может представлять собой любое число с плавающей точкой в диапазоне от 0 до 1, умноженное на 231-1. Это значение также можно установить при помощи функции PostgreSQL setseed. Например:

SELECT setseed(value); SEVER ENCODING;

Устанавливается мультибайтовая кодировка для серверов, скомпонованных с мульти-байтовой поддержкой.

Ниже приводится пример установки формата даты и времени стиля Oracle и European.

SET DATESTYLE ТО sql, European;

SOL Server

Платформа SQL Server поддерживает присваивание значений переменным при помощи инструкции SET, если эти переменные были ранее созданы при помощи инструкции DECLARE, а также присваивание значений переменным курсоров. (Также SQL Server использует инструкцию SET для других целей, например для включения и отключения флагов сеанса командами типа SETNOCOUNT ON.) Синтаксис, специфичный для данной платформы, приводится ниже.

Данная инструкция не поддерживает ключевое слово DEFAULT, но во всех прочих отношениях поддерживает синтаксис ANSI. Значение имя_сервера должно ссылаться на соединение, указанное в предыдущей инструкции CONNECT, либо в форме константы, либо в форме переменной.

Последнее обновление: 14.08.2017

Через переменные мы можем передавать данные в запросы. И также мы можем получать данные, которые являются результатом запросов, в переменные. Например, при выборке из таблиц с помощью команды SELECT мы можем извлекать данные в переменную с помощью следующего синтаксиса:

SELECT @переменная_1 = спецификация_столбца_1, @переменная_2 = спецификация_столбца_2, ...................................... @переменная_N = спецификация_столбца_N

Кроме того, в выражении SET значение, присваиваемое переменной, также может быть результатом команды SELECT.

Например, пусть у нас будут следующие таблицы:

CREATE TABLE Products (Id INT IDENTITY PRIMARY KEY, ProductName NVARCHAR(30) NOT NULL, Manufacturer NVARCHAR(20) NOT NULL, ProductCount INT DEFAULT 0, Price MONEY NOT NULL); CREATE TABLE Customers (Id INT IDENTITY PRIMARY KEY, FirstName NVARCHAR(30) NOT NULL); CREATE TABLE Orders (Id INT IDENTITY PRIMARY KEY, ProductId INT NOT NULL REFERENCES Products(Id) ON DELETE CASCADE, CustomerId INT NOT NULL REFERENCES Customers(Id) ON DELETE CASCADE, CreatedAt DATE NOT NULL, ProductCount INT DEFAULT 1, Price MONEY NOT NULL);

Используем переменные при извлечении данных:

DECLARE @maxPrice MONEY, @minPrice MONEY, @dif MONEY, @count INT SET @count = (SELECT SUM(ProductCount) FROM Orders); SELECT @minPrice=MIN(Price), @maxPrice = MAX(Price) FROM Products SET @dif = @maxPrice - @minPrice; PRINT "Всего продано: " + STR(@count, 5) + " товарa(ов)"; PRINT "Разница между максимальной и минимальной ценой: " + STR(@dif)

В данном случае переменная @count будет содержать сумму всех значений из столбца ProductCount таблицы Orders, то есть общее количество проданных товаров.

Переменные @min и @max хранят соответственно минимальное и максимальное значения столбца Price из таблицы Products, а переменная @dif - разницу между этими значениями. И подобно простым значениям, переменные также могут участвовать в операциях.

Другой пример:

DECLARE @sum MONEY, @id INT, @prodid INT, @name NVARCHAR(20); SET @id=2; SELECT @sum = SUM(Orders.Price*Orders.ProductCount), @name=Products.ProductName, @prodid = Products.Id FROM Orders INNER JOIN Products ON ProductId = Products.Id GROUP BY Products.ProductName, Products.Id HAVING Products.Id=@id PRINT "Товар " + @name + " продан на сумму " + STR(@sum)

Здесь извлекаемые данные из двух таблиц Products и Orders группируются по столбцам Id и ProductName из таблицы Products. Затем данные фильтруются по столбцу Id из Products. А извлеченные данные попадают в переменные @sum, @name, @prodid.