Процедурное программирование на SQL

1 Процедурные возможности Transact-SQL
На сегодняшний день сложилась такая ситуация, при которой база данных уже не может ограничиться выполнением только основных задач с использованием для этого операторов определения данных и операторов управления данными. Понимая необходимость повысить гибкость средств управления базой данных, Microsoft paзработал так называемые управляющие операторы. Они выполняют действия, по¬добные действиям эквивалентных операторов в процедурных языках программирования. Это подразумевает возможность объявления переменных, использования операторов IF и WHILE, выдачи сообщений пользователям с помощью оператора PRINT, а также множество других функций.
Кроме повышения функциональности операторов определения и операторов управления данными, управляющие операторы позволяют добиться большей гибко¬сти при выполнении различных операций над хранящейся в базе данных информа¬цией. Например, перед обновлением данных отнюдь нелишне убедиться в самом факте существования этих данных. Также очень часто требуется определить влия¬ние внесенных в таблицу изменений на другие таблицы базы данных. Несмотря на то, что приведенные примеры могут показаться не совсем понятными и очевидными, они, тем не менее, должны дать хотя бы общее представление о преимуществах ис¬пользования управляющих операторов.
Рассмотрим способ использования и применения на практи¬ке четырех базовых управляющих операторов:
оператора объявления переменной;
оператора присвоения переменной значения;
оператора IF;
оператора WHILE.
1.1 Объявление переменных
Как правило, отправной точкой изучения практически любого языка программи¬рования является знакомство со способом объявления и использования перемен¬ных. Итак, последуем этой схеме и рассмотрим способ объявления и использования переменных в Transact-SQL.
Объявление переменной в MS SQL Server почти полностью аналогично объяв¬лению переменной в подавляющем большинстве языков программирования, за ис¬ключением одного момента. В MS SQL Server перед именем переменной обязатель¬но должен стоять символ (префикс) @.
После имени указывается тип переменной и при необходимости ее размер. В од¬ной строке кода Transact-SQL можно разместить сразу несколько объявлений пере¬менных (в качестве альтернативы размещению каждого объявления переменной на отдельной строке). Например:

1: DECLARE @MyChar CHAR(9), @MyINT INTEGER, @MyDate DATETIME

Размещение объявления одной переменной в отдельной строке избавляет от необходимости использования запятых, но, к сожалению, обязывает указывать в на¬чале каждой строки ключевое слово DECLARE.

1: DECLARE @MyChar CHAR(9)
2: DECLARE @MyINT INTEGER
3: DECLARE @MyData DATETIME

1.2 Присвоение переменным значения с помощью оператора SET
Как правило, самым актуальным после объявления переменной является вопрос инициализации. Инициализация (initialization.) — присвоение переменной ее начального значения.
Одна из рекомендаций Microsoft — использовать для присвоения значения переменной оператор SET вместо оператора SELECT. Ниже рассматриваются примеры использования обоих операторов, однако, как отмечает Microsoft, оператор SET специально оптимизирован для выполнения операции присвоения. Для того чтобы присвоить значение переменной @MyChar, введите следующий код в окно ввода кода программы Редактор запросов:

1: DECLARE @MyChar CHAR(9)
2: SET @MyChar = ‘SQLServer’

В качестве альтернативы вместо оператора SET можно использовать оператор SELECT:

1: DECLARE @MyChar CHAR(9)
2: SELECT @МуChar = ‘SQLServer’

И хотя с позиций кода разница между двумя управляющими операторами совсем не значительна, при дальнейшей разработке приложения будем придерживаться рекомендаций Microsoft. Остался невыясненным один из самых главных вопросов: зачем вообще может понадобиться объявление переменной и присвоение ей значения? Наиболее очевидный ответ — необходимость проверки существования некоторого значения для того, чтобы убедиться в корректности заданного условия. Каким же образом это достигается с использованием переменных? И что делать в том случае, если переменной необходимо присвоить значение, взятое из таблицы? Пред¬ставьте себе ситуацию, в которой переменной необходимо присвоить значение из столбца Фамилия таблицы Человек, чтобы проверить, не содержит ли оно символов пробела. Подобную задачу легко решить, выполнив следующий код:

1: DECLARE @MyChar CHAR(9)
2: SET @MyChar = (SELECT Фамилия FROM Человек WHERE ЧеловекИдн = 1)
3: SELECT @MyChar

В результате выполнения такого кода MS SQL Server возвратит имя чело-века из таблицы Человек с идентификационным номером 1. В строке 3 указывается необходимость вывода присвоенного переменной @MyChar значения. В случае отсут¬ствия этой строки переменной @MyChar по прежнему будет присваиваться значение, однако пользователь не сможет его просмотреть.
Как видите, комбинирование в коде Transact-SQL операторов управления дан¬ными и управляющих операторов не представляет никакой трудности. По мере раз¬работки вашего проекта будет рассмотрено еще немало подобных приведенному выше примеру.
Итак, что же делать после того, как переменной было присвоено значение?
1.3 Оператор проверки условия IF
После присвоения переменной значения самым «ожидаемым» действием являет¬ся сравнение этого значения с каким-либо образцом. Для этого в Transact-SQL суще¬ствует специальный управляющий оператор IF.
Оператор IF является одним из наиболее распространенных во всех языках про-граммирования. Он позволяет провести проверку истинности заданного условия и выполнить, в зависимости от исхода проверки, то или иное действие. С помощью оператора IF можно установить существование заданного значения, а также выяс¬нить, равно ли оно, больше или меньше какого-либо другого значения. Оператор про¬верки условия IF состоит из двух частей: собственно оператора IF и оператора ELSE.
Оператор ELSE выполняется только в случае ложности заданного в операторе IF условия. Рассмотрим пример, в котором переменной @MyDate присваивается неко¬торое значение, а затем проводится проверка соответствия этого значения опреде¬ленному условию. В зависимости от исхода проверки условия в области результата выполнения кода программы Редактор запросов будет выведено соответствующее сооб¬щение. Итак, введите и выполните код, приведенный в листинге 4.

Листинг 4. Проверка условия и вывод результата проверки
1: DECLARE @MyDate DATETIME
2: SET @MyDate = GETDATE()
3: IF @MyDate = GETDATE()
4: PRINT ‘Это сегодня’
5: ELSE
6: PRINT ‘Это не сегодня’

В результате выполнения кода MS SQL Server возвратит сообщение «Это сегодня».
Являясь встроенной функцией MS SQL Server, GETDATE() возвращает текущее значение даты на сервере. Ее аналогом может выступать функция Now() в языке программирования Visual Basic.
Теперь измените значение, присваиваемое переменной @MyDate. и вновь выпол¬ните код, обновленный вариант которого приведен в листинге 5.

Листинг 5. Проверка условия — выполнение оператора else
1: DECLARE @MyDate DATETIME
2: SET @MyDate = (SELECT ДатаРождения FROM Человек WHERE Фамилия = ‘Николаенко’)
3: IF @MyDate = GETDATE()
4: PRINT ‘Это сегодня’
5: ELSE
6: PRINT ‘Это не сегодня’

В результате выполнения кода с измененным значением переменной @MyDate SQL Server возвратит сообщением ‘Это не сегодня’.
Выше был приведен достаточно простой, но очень наглядный пример практиче-ского использования оператора IF, ELSE. Уверен, что немного поразмыслив, вы найдете массу других способов использования этого оператора. Например, оператор IF может быть использован для проверки существования определенной записи в таблице Клиент перед обновлением информации в таблице Сотрудник.
1.4 Использование цикла WHILE
Итак, рассмотрены три из четырех основных управляющих операторов, которые предполагалось обсудить в этой части лабораторной работы. Перейдем с оставшемуся управляющему оператору — WHILE.
Как и большинство операторов Transact-SQL, WHILE состоит из нескольких частей. Следует отметить, что не все части этого оператора обязательны дня построения полноценного выражения WHILE. С позиций синтаксиса структура базового оператора WHILE фактически аналогична структуре цикла WHILE в большинстве языков программирования. Цикл WHILE выполняется до тех пор, пока остается истинным условие цикла. Как только это условие перестает быть истинным, работа цикла прекращается.
Рассмотрим пример использования оператора WHILE. В результате выполнения приведенного в листинге 6 цикла отображаются значения счетчика.

Листинг 6. Использование цикла WHILE для вывода значений счетчика
1: DECLARE @MyCounter INT
2: SET @MyCounter=1
3: WHILE @MyCounter<10
4: BEGIN
5: PRINT ‘Значение счетчика сейчас равно ‘
5a: + CONVERT(CHAR(2), @MyCounter)
6: SET @MyCounter = @MyCounter+1
7: END

MS SQL Server будет продолжать выполнять тело цикла до тех пор, пока условие цикла не станет ложным.

Условие приведенного выше цикла становится в определенный момент ложным, поскольку на каждом шаге цикла происходит увеличение значения переменной @MyCounter.

Прежде чем запустить цикл WHILE, следует убедиться в том, что его усло¬вие когда-нибудь станет ложным, так как в противном случае можно по¬пасть в довольно неприятную ситуацию, столкнувшись с так называемым бесконечным циклом (или, проще говоря, зацикливанием).
Бесконечный цикл — это цикл, никогда не прекращающий выполняться из-за того, что его условие никогда не может стать ложным. Для того чтобы прекратить выполнение бесконечного цикла, в Management Studio следует щелкнуть на расположенной на панели инструментов кнопке с изображени¬ем красного квадрата.
Уверен, что приведенный выше код Transact-SQL уже успел заинтриго¬вать вас своими новыми, не рассматривавшимися ранее элементами. В первую очередь это ключевые слова BEGIN…END, расположенные в строках 4 и 7, которые представляют собой еще один управляющий оператор. Функции управляющего оператора BEGIN…END полностью совпадают с функциями аналогичных конструкций во многих языках программирования, например в школьном языке Pascal. Этот оператор позволяет сгруппировать в блок несколько операторов Transact-SQL. Ключевое слово END указывает на окончание текущего блока операторов.

Цикл WHILE требует обязательного наличия блока BEGIN. . . END, в котором может быть расположен один и более операторов Transact-SQL.
Следующим интересным моментом, который стоит отметить, является использо¬вание в строке 5а функции CONVERT. Эта функция позволяет изменить тип данных переменной @MyCounter с INT на CHAR длиной 2 символа. Зачем это нужно? Дело в том, что управляющий оператор PRINT может выводить на экран только данные строкового типа. Все, что не является строкой, на экран вывести нельзя.
Обратите внимание на расположенный на той же строке символ «плюс» (+). В данном случае он предназначен для формирования сообщения путем присоедине¬ния к нему значения переменной @MyCounter. Именно таким способом можно заста¬вить MS SQL Server выводить каждый раз текущее значение счетчика.
Что касается метода увеличения счетчика, то я уверен, что, посмотрев на код в строке 6, вы и сами разберетесь, что к чему. Можно лишь отметить, что новое зна¬чение переменной @MyCounter формируется путем прибавления единицы к текуще¬му значению этой переменной. Таким образом, если текущее значение переменной @MyCounter было равно 7, то ее новое значение будет получено по формуле 7+1.
Как упоминалось ранее, цикл WHILE состоит из нескольких частей и позволяет ком-бинировать другие управляющие операторы (что, кстати, и было продемонстрирова¬но). Единственным существенным моментом, который еще не был рассмотрен, являет¬ся возможность использования внутри цикла WHILE специального управляющего оператора BREAK. Этот оператор позволяет немедленно прекратить выполнение цикла в случае выполнения какого-либо заданного условия. Обратите внимание на код, при¬веденный в листинге 7, который фактически дополняет код из листинга 6.

Листинг 7. Добавление оператора BREAK в цикл WHILE
1: DECLARE @MyCounter INT
2: SET @MyCounter = 1
3: WHILE @MyCounter < 10
4: BEGIN
5: PRINT ‘ Значение счетчика сейчас равно ‘
5a: + CONVERT(CHAR(2), @MyCounter)
6: SET @MyCounter = @MyCounter + 1
7: IF @MyCounter = 5
8: BEGIN
9: PRINT ‘Выход из цикла’
10: BREAK
11: END
12: END

MS SQL Server продолжает выполнение цикла до тех пор, пока заданное в строке 7 условие не становится истинным. Отметьте, что, хотя условие цикла по-прежнему остается истинным (значение переменной @MyCounter все еще меньше 10), расположенный в теле цикла оператор BREAK позволяет немедленно прекратить его выполнение.
Обратите внимание на соответствующий оператору IF блок BEGIN…END. Данный блок предназначен для группировки операторов Transact-SQL, рас¬положенных в строках 9 и 10. Без блока BEGIN…END цикл завершит свою работу, как только достигнет оператора BREAK в строке 10. Попробуйте уб¬рать ключевые слова BEGIN и END и убедитесь в этом сами.
А зачем, собственно, может понадобиться выход из цикла WHILE, прежде чем его основное условие станет ложным? Дело в том, что проверка дополнительного усло¬вия внутри тела цикла не только позволяет установить истинность или ложность какого либо значения, но и выявить некорректную или недопустимую информацию. Обнаружив ошибку, можно немедленно прервать цикл, избежав тем самым дополнительных расходов на его дальнейшее выполнение и, что еще хуже, возможных ошибок при внесении изменений в таблицу.
Итак, мы только что завершили вводный курс в управляющие операторы языка Transact-SQL. Несмотря на то что «курс» вышел несколько облегченным, знание основных управляющих операторов послужит вам хорошей основой при дальнейшем изучении управляющих операторов Transact-SQL.

автор — преподаватель штучного интелекта.

Использование материалов с сайта разрешаем при условии, что будет указан первоисточник (активная ссылка на наш сайт)