Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
17-06-2015_23-01-11 / Учебное пособие ИОБД_2013.doc
Скачиваний:
138
Добавлен:
15.02.2016
Размер:
2.9 Mб
Скачать

7.5. Средства разработки процедур деловой логики в Transact-sql

Команды Transact-SQL могут быть сгруппированы в пакет. Пакет является последовательностью команд и операторов, которые являются процедурными расширениями языка. Преимуществом пакета перед группой одиночных команд является выигрыш в производительности.Операторы, являющиеся процедурными расширениями языка, позволяют реализовать такие управляющие конструкции как группировка команд, ветвление и циклы.

К процедурным расширениям относятся следующие операторы:

BEGIN … END - выполняет группировка двух и более команд в единый блок. Объединенные в блок команды воспринимаются интерпретатором как одна команда.

Синтаксис конструкции:

BEGIN

команда_1

команда_2

:

команда_n

END

Блоки BEGIN .. END могут быть вложенными. Ограничений на глубину вложенности нет.

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

Синтаксис оператора:

IF логическое_условие

блок_команд_1

[ ELSE

блок_команд_2 ]

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

Оператор CASE позволяет реализовать разветвления по многим направлениям.

Синтаксис оператора:

CASE

WHEN логическое_условие THEN блок_команд

[… n]

[ ELSE блок_команд ]

END

В операторе может быть указано множество блоков WHEN…THEN, о чем свидетельствует параметр […n].

Если логическое условие первого блока WHEN…THEN возвращает значение TRUE, то выполняется указанный блок команд и оператор CASE завершает свою работу. Если логическое условие возвращает значение FALSE, то проверяется логическое условие следующего блока. Если ни одно из указанных условий не выполняется , то после ключевого слова ELSE можно указать выполняемый в этом случае блок команд.

Для организации цикла и работы в нем используются операторы WHILE, BREAK, CONTINUE.

Синтаксис оператора:

WHILE логическое_условие

BEGIN

блок_команд

[BREAK]

блок_команд

[CONTINUE]

блок_команд

END

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

Представления

Представление (views) – это виртуальная таблица, содержимое которой определяется запросом. Физически представление реализуется как инструкция SELECT, на основе которой производится выборка данных из одной или нескольких таблиц или представлений.

Команда создания представления имеет следующий синтаксис:

CREATE VIEW имя_представления[(имя_столбца[, …)]]

AS команда_select

[WITH CHECK OPTION]

Если в команде новые имена столбцов не заданы явно, то они наследуются из таблиц базы данных.

Параметр WITH CHECK разрешает вставку и обновление записей таблиц через представление в том случае, если эти записи получены выборкой из представления.

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

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

Пример. Создание представления для получения следующих сведений о студента: группа, фамилия, дисциплина, оценка.

CREATE VIEW [результаты сессии]

AS

SELECT 'Группа'=s.[номер группы], [фамилия], 'Дисциплина'=[наименование дисциплины], [оценка]

FROM [дисциплина] d INNER JOIN [общая ведомость] v ON d.[код дисциплины] = v.[код дисциплины]

INNER JOIN [студент] s

ON v.[номер зачетной книжки] = s.[номер зачетной книжки]

Теперь, представление [результаты сессии] можно использовать в запросах как таблицу.

Пример. Используя представление [результаты сессии] получить сведения о результатах экзаменов студентов группы 1191:

SELECT * FROM [результаты сессии]

WHERE Группа= 1191

Пример. Используя представление [результаты сессии] получить сведения о результатах сдачи экзамена по дисциплине Маркетинг. Упорядочить полученные данные по возрастанию значения фамилия студента:

SELECT * FROM [результаты сессии]

WHERE Дисциплина = 'Маркетинг' ORDER BY [фамилия]

Пример. Используя представление [результаты сессии] определить средний балл каждого студента:

SELECT фамилия, [средний балл]=avg(cast(оценка AS DECIMAL(3,2)))

FROM [результаты сессии]

GROUP BY фамилия

Пользовательские функции

Пользовательская функция это именованный пакет команд, который хранится на сервере. Особенностью функции является то, что после своего выполнения она всегда возвращает одно значение. В Transact - SQL можно создать следующие классы функций пользователя.

SCALAR — эти функции характеризуются тем, что возвращают обычное скаляр­ное значение любого из типов данных, поддерживаемых, за исключением типов данных text, ntext, image, table . Функция может включать множество команд, которые объединяются в один блок с помощью конструкции BEGIN...END.

INLINE — это функции, которыя со­держит всего одну команду — SELECT, которая фор­мирует набор данных, возвращаемый возвращается пользователю в виде зна­чения типа данных table.

MULTISTATEMENT — это функция также возвращает пользователю значение типа данных table, но может содержа­ть набор данных.

Синтаксис команды создания SCALAR-функции:

CREATE FUNCTION имя_функции (@переменная тип_данных [,…])

RETURNS тип_данных_возвращаемого_значения

AS

BEGIN

Команды Transact-SQL

RETURN возвращаемое_значение

END

Вызов SCALAR-функции выполняется в разделах SELECT, WHERE, HAVING

Пример. Создать запрос на создание функции с именем [Средний балл студента], которая должна служит для расчета среднего балла студента по данным таблицы ОБЩАЯ ВЕДОМОСТЬ.

Create FUNCTION [Средний балл студента] (@номер_зачетной_книжки as char(8))

RETURNS decimal(3,2)

BEGIN

DECLARE @средний_балл decimal(3,2)

select @средний_балл =cast(avg(cast(оценка as decimal(3,2))) as decimal(3,2))

from [общая ведомость]

where [номер зачетной книжки]=@номер_зачетной_книжки

return @средний_балл

END

Для применения пользовательской скалярной функции следует префиксом указать имя владельца (схемы). Ниже показан пример вызова функции [Средний балл студента]:

SELECT фамилия, dbAdmin.[Средний балл студента] ([номер зачетной книжки]) AS [средний балл]

FROM студент

WHERE [номер группы]=1191

INLINE и MULTISTATEMENT функции являются табличными, так как возвращают набор данных. Предложение RETURNS задает тап возвращаемого значения TABLE.

Синтаксис команды создания INLINE -функции:

CREATE FUNCTION имя_функции (@переменная тип_данных [,…])

RETURNS table

AS

RETURN (команда SELECT)

Предложение RETURNS задает тап возвращаемого значения TABLE. Структура набора данных определяется запросом SELECT. Так как INLINE – функции возвращает набор данных, то вызов функции указывается в разделе FROM. Синтаксис вызова:

SELECT

FROM имя_пользователя.имя_функции

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

Create FUNCTION [Средние баллы группы] (@номер_группы smallint )

RETURNS table

AS

return (select фамилия ,

cast(avg(cast(оценка as decimal(3,2))) as decimal(3,2)) as [средний балл]

from [общая ведомость] a inner join студент b on a.[номер зачетной книжки]=b.[номер зачетной книжки]

where [номер группы]=@номер_группы

group by фамилия)

Выполнить INLINE-функцию можно путем ее включения в предложение FROM:

SELECT фамилия,[средний балл)]

FROM dbAdmin.[Средние баллы группы] (1191)

ORDER BY 2 DESC

Синтаксис команды создания MULTISTATEMENT-функции:

CREATE FUNCTION имя_функции (@переменная тип_данных [,…])

RETURNS @переменная table(список_столбцов)

AS

BEGIN

Команда Transact-SQL

RETURN

END

Функция возвращает значение в переменную @переменная типа TABLE.

Вызов MULTISTATEMENT – функции указывается в разделе FROM. Синтаксис вызова:

SELECT

FROM имя_пользователя.имя_функции

Пример. Пользовательская MULTISTATEMENT-функция [Результаты сессии студента] служит для получения отдельной ведомости студента о сданных экзаменах по заданному номеру зачетки.

create FUNCTION [Результаты сессии студента] ( @studentID char(8))

RETURNS @ved TABLE(фамилия char(15),

[наименование дисциплины] char(40), оценка tinyint)

AS

BEGIN

INSERT @ved

SELECT фамилия, [наименование дисциплины], оценка

FROM студент s inner join [общая ведомость] v on s.[номер зачетной книжки]=

v.[номер зачетной книжки] inner join дисциплина d on v.[код дисциплины] = d.[код дисциплины]

WHERE s.[номер зачетной книжки] = @studentID

RETURN

END

В предложении RETURNS указаны имя табличной переменной @ved, ее тип TABLE и структура, соотвестствующая этому питу(список столбцов и их типов данных). В теле функции оператор INSERT заполняет таблицу. При выполнении оператора RETURN он просто возвращает табличную переменную, указанную выше в RETURNS.

Выполнить MULTISTATEMENT-функцию можно так же, как и INLINE-функцию путем ее включения в предложение FROM:

SELECT * FROM [Результаты сессии студента] ('10121/10')

Хранимые процедуры

Хранимая процедура — это именованный набор команд Transact-SQL, хранящийся непосредственно на сервере и представляющий собой самостоятельный объект базы данных. Без хранимых процедур пользователю пришлось бы вводить весь набор команд всякий раз, когда он хочет выпол­нить какое-либо действие.

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

Синтаксис команды создания хранимой процедуры:

CREATE PROCEDURE имя_процедуры

@параметр тип_данных [OUTPUT] [,…]

AS

команды Transact-SQL

При создании хранимой процедуры с помощью @переменная можно задать параметр процедуры. Процедура принимает значение в переменную всякий раз, когда осуществляется ее вызов. Хранимые процедуры могут возвращать значения с помощью параметров, в этом случае параметр должен быть объявлен как OUTPUT.

Синтаксис вызова процедуры:

EXEC[UTE] имя_процедуры @параметр= {значение |@переменная|DEFAULT}[OUTPUT] [,…]

Значения параметру может быть присвоено с использованием значения, переменной или значения DEFAULT

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

create PROCEDURE [Сведения о факультетах]

AS

select [наименование факультета],count(distinct [номер специальности])as [количество специальностей],

count(distinct b.[номер группы]) as [количество групп],count(фамилия) as [количество студентов]

from факультет a inner join группа b on a.[номер факультета]=b.[номер факультета]

inner join студент c on b.[номер группы]=c.[номер группы]

group by [наименование факультета]

Пользовательская хранимая процедура [Сведения о факультетах] может быть вызвана следующими образом:

EXEC [Сведения о факультетах]

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

CREATE PROCEDURE [результаты экзамена группы]

@disname varchar(40),

@groupnumber smallint

AS

SELECT 'Группа'=s.[номер группы], [фамилия], 'Дисциплина'=[наименование дисциплины], [оценка]

FROM [дисциплина] d INNER JOIN [общая ведомость] v ON d.[код дисциплины] = v.[код дисциплины] INNER JOIN [студент] s

ON v.[номер зачетной книжки] = s.[номер зачетной книжки]

WHERE d.[наименование дисциплины] = @disname AND s.[номер группы] = @groupnumber

Пользовательская хранимая процедура [результаты экзамена группы] может быть вызвана следующими способами:

- с указанием только значений параметров:

EXEC [результаты экзамена группы] ‘КСТ СУБД', ‘3591’

- с помощью именованных параметров в заданном порядке:

EXEC [результаты экзамена группы] @disname=‘Численные методы', @groupnumber=‘3591'

- с помощью именованных параметров в произвольном порядке:

EXEC [результаты экзамена группы] groupnumber=‘3591', @disname=‘Философия'

Пример. Создание и использование пользовательской хранимой процедуры с OUTPUT-параметром. Процедура определяет средний балл студента по результатам сессии. Хранимая процедура использует вводной параметр – номер зачетки @номер_студента, принимающий вводное значение, заданное при вызове и выводной параметр – средний балл @средний_балл, используемый для возврата значения в вызывающую программу.

CREATE PROCEDURE [средний балл студента]

@номер_студента char(8),

@средний_балл decimal(3,2) OUTPUT

AS

SELECT @средний_балл = CONVERT(decimal(3,2), AVG( CAST([оценка] AS decimal(3,2))))

FROM [общая ведомость]

GROUP BY [номер зачетной книжки]

HAVING [номер зачетной книжки]=@номер_студента

RETURN

Следующий пакет предназначен для вызова хранимой процедуры с указанием значения для вводного параметра (зачетки № 10005/10) и сохраняет выводное значение хранимой процедуры в переменной @средний_балл_студента, являющейся локальной для вызывающей программы.

DECLARE @средний_балл_студента decimal(4,2)

EXECUTE [средний балл студента] '10005/01', @средний_балл = @средний_балл_студента OUTPUT

-- Вывод значения, возвращенного процедурой:

SELECT 'Средний балл студента с зач. № "10005/01": ' + convert(varchar(6), @средний_балл_студента)

GO

Триггеры

Триггер – это специальный тип хранимой процедуры, которая запускается автоматически при изменении какой-либо таблицы одной из трех команд языка манипулирования данными: UPDATE, INSERT, DELETE. Эти операции по отношению к триггеру называют событиями модификации данных. В отличие от других типов хранимых процедур триггеры запускаются автоматически при указанных событиях модификации; их нельзя запустить по имени. Триггер создается с указанием (привязкой) к одной таблице, но он может выполнять доступ и к другим таблицам и объектам. С помощью триггеров можно реализовать так называемые бизнес-правила приложений. Примером бизнес-правила является, например, следующее правило - при добавлении в таблицу Общая ведомость оценки студента следует определить, является ли он коммерческим студентом и учится ли студент на одни пятерки. Если да, то его необходимо добавить в таблицу отличников, содержащую сведения о тех студентах, которые переводятся на бюджет, и только в том случае если его там нет. Если добавляемая оценка коммерческого студента не пятерка, то данные о нем следует удалить из таблицы отличников.

Синтаксис команды создания триггера:

CREATE TRIGGER имя_триггера

ON имя_таблицы

{FOR|AFTER|INSTEAD OF} {INSERT |UPDATE | DELETE}

AS

команды Transact-SQL

Опции AFTER и INSTEAD-OF определяют тип триггера.

Триггеры AFTER выполняются после успешного выполнения действий, обрабатываемых триггером. AFTER – триггер можно задать с помощью ключевых слов AFTER или FOR. Триггеры этого типа могут создаваться только для базовых таблиц.

INSTEAD OF-триггер выполняется взамен действий, обрабатываемых триггером. Тем самым, запрос пользователя переопределяется, и вносятся изменения, осуществляемые в теле триггера. INSTEAD OF-триггеры могут создаваться как для таблиц, так и для представлений.

При активизации триггера создают две временные таблицы deleted и inserted. Структуры этих таблиц полностью соответствуют структуре таблицы триггера.

Таблица deleted содержит копии строк, которые были удалены из таблицы. Таблица используется в триггерах для команд DELETE или UPDATE.

Таблица inserted содержит копии строк, добавленных к таблице триггера оператором INSERT или UPDATE.

При выполнении оператора UPDATE старые записи копируются в deleted, а новые – в таблицу триггера и в inserted. Значения таблиц deleted и inserted доступны только из триггера.

После завершения работы триггера эти таблицы больше не доступны.

Пример. Создание AFTER - триггера к таблице Студент. Триггер DeleteStud должен активизироваться при удалении записи в таблице Студент для каскадного удаления записей этого студента в Общей ведомости. Перед удалением записей триггер переносит записи студента из общей ведомости в архивную ведомость. Таблица Архивная ведомость должна быть предварительно создана и имеет структуру такую же, как и Общая ведомость.

CREATE TRIGGER DeleteStud

ON [студент]

FOR DELETE

AS

INSERT INTO [Архивная ведомость]

SELECT v.[номер группы], v.[код дисциплины], v.[номер зачетной книжки], v.[оценка]

FROM [общая ведомость] v inner join deleted d

on d.[номер зачетной книжки] = v.[номер зачетной книжки]

PRINT 'Записи ведомости, перенесенные в архив:'

SELECT * FROM [Архивная ведомость]

DELETE [общая ведомость]

FROM [общая ведомость] v inner join deleted d

on d.[номер зачетной книжки] = v.[номер зачетной книжки]

PRINT 'Записи ведомости удалены'

GO

Каждое использование оператора DELETE активизирует триггер.

DELETE [студент] WHERE [номер зачетной книжки] = '11247'

Можно создавать множество триггеров для каждой таблицы и для каждого действия: UPDATE, INSERT, DELETE. По умолчанию не существует порядка, в котором выполняется несколько триггеров для конкретного действия. Есть возможность задать будет ли триггер первым, или последним выполняемым триггером.

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

sp_settriggerorder [ @triggername = ] 'имя_триггера' , [ @order = ] 'значение'

Параметр @order может принимать три значения: first, last, none (порядок не определен).

Как уже было сказано выше, INSTEAD OF триггер выполняется вместо действий обрабатываемых триггером. К значениям столбцов базовой таблицы, поставляемым триггером, обрабатываемым команды INSERT и UPDATE, предъявляются следующие требования:

- значения не могут быть заданы для вычисляемых столбцов;

- значения не могут быть заданы для столбцов со свойством IDENTITY.

Пример. Создать INSTEAD OF триггер, который при обновлении значения оценки в таблице ОБЩАЯ ВЕДОМОСТЬ будет выполнять проверку вводимого значения.

create trigger [update_проверка оценки] on [общая ведомость]

instead of update

as

declare @оценка tinyint

declare @НЗК char(8)

declare @КД int

select @КД=[код дисциплины], @НЗК=[номер зачетной книжки]

from deleted

select @оценка =оценка

from inserted

if @оценка <3 or @оценка >5

begin

print 'ошибка при вводе оценки'

ROLLBACK TRANSACTION

end

else

update [общая ведомость]

set [оценка]=@оценка

where [код дисциплины]=@КД and [номер зачетной книжки]=@НЗК

В примере реализовано так называемое декларативное ограничение целостности данных – целостность домена, которое можно реализовать с помощью операторов CREATE TABLE, ALTER TABLE. Триггер использовать целесообразно в том случае, если такое ограничение должно действовать только в определенный период времени. В основном триггер является механизмом, с помощью которого можно реализовать процедурные ограничения целостности данных.

Соседние файлы в папке 17-06-2015_23-01-11