- •Тарзанов в.В.
- •Предисловие
- •Введение
- •Информационное обеспечение информационных систем
- •1.1.Понятие информационной системы и ее структура
- •1.2.Структура экономической информации
- •1.3.Структура информационного обеспечения
- •1.4.Системы классификации и кодирования экономической информации
- •1.5.Понятие унифицированной системы документации
- •1.6.Понятие электронного документооборота
- •Основные понятия теории баз данных
- •2.1.Общие положения
- •2.2.Классификация баз данных
- •2.3.Уровни, виды и типы моделей данных
- •3. Реляционная модель данных
- •3.1. Основные понятия реляционной модели данных
- •Тип данных
- •3.2.Фундаментальные свойства отношений
- •3.3. Составные части (аспекты) реляционной модели
- •4. Проектирование реляционных баз данных
- •4.1.Основные этапы проектирования
- •4.2. Проектирование методом нормальных форм
- •Первая нормальная форма (1nf)
- •Вторая нормальная форма (2nf)
- •Третья нормальная форма (3nf)
- •Нормальная форма Бойса-Кодда (bcnf)
- •Четвертая нормальная форма (4nf)
- •Пятая нормальная форма (pj/nf)
- •4.3. Проектирование базы данных «Университет»
- •5. Автоматизация проектирования баз данных
- •5.1. Общая характеристика case-средств
- •5.2. Семантическая модель данных
- •5.3. Структурная схема автоматизированного проектирования базы данных
- •6. Базисные средства манипулирования данными
- •6.1. Элементы реляционной алгебры
- •6.2. Основные операции реляционной алгебры
- •А Номер факультета Наименование Декан 2 фом Сидоров
- •А Наименование Декан Экономический Петров фом Сидоров
- •6.3. Элементы реляционного исчисления
- •7. Структурированный язык запросовtransactsql
- •7.1. Основы языка Transact-sql
- •7.2. Функции sql
- •7.3. Команды языка определения данных
- •7.4. Команды языка манипулирования данными
- •7.5. Средства разработки процедур деловой логики в Transact-sql
- •8. Основные функции и типовая организация современных систем управления базами данных
- •8.1. Основные функции систем управления базами данных
- •8.2. Типовая организация систем управления базами данных
- •8.3. Архитектуры приложений, использующих базы данных
- •Заключение
- •Контрольные вопросы
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. Триггер использовать целесообразно в том случае, если такое ограничение должно действовать только в определенный период времени. В основном триггер является механизмом, с помощью которого можно реализовать процедурные ограничения целостности данных.