Практическая работа

Создание генератора и триггеров. Каскадные воздействия

Создание генераторов

1.  Вызовите SQL Explorer и откройте БД IB_BIBL_ХХ. Выполните такой запрос: CREATE GENERATOR GEN_NAKLS

2.  К сожалению, в операторе SET GENERATOR начальное значение не может быть результатом запроса SELECT. Поэтому сначала с помощью следующего оператора получите (и запомните) очередное значение, которое нужно поместить в столбец NaklID таблицы NAKLS:

SELECT MAX(NaklID)+1 FROM Nakls

3.  Далее установите начальное значение генератора:

SET GENERATOR Gen_Nakls TO число

Здесь число — значение, полученное предыдущим оператором SELECT.

4.  Создайте таким же образом генераторы GEN_BOOKS, GEN_FIRMS, GEN_ PAYMENTS и GEN_MOVEOOK для соответствующих таблиц.

Создание триггеров

5.  С помощью триггеров можно установить в автоинкрементное поле значение, полученное от генератора. Создайте такой триггер:

CREATE TRIGGER BEF_INS_NAKLS FOR Nakls

ACTIVE BEFORE INSERT

AS

BEGIN

NEW. NakllD = GEN_ID(GEN_NAKLS,1);

END

В первой строке помимо имени триггера BEF_INS_NAKLS (хотя триггеры нельзя вызвать обращением к ним по имени в хранимых процедурах или SQL-запросах, они, как и все другие сущности серверной БД, должны иметь уникальные имена) указывается также таблица Nakls, для которой он предназначен. Следующая строка указывает, когда триггер должен активизироваться (в нашем случае — перед встав­кой новой записи). Третья строка содержит зарезервированное слово AS, которым открывается тело триггера. Тело триггера всегда (даже если триггер содержит един­ственный оператор, как в нашем случае) должно ограничиваться парой ключевых слов BEGIN и END. В пятой строке расположен единственный исполняемый опера­тор, в котором новому значению (предикат NEW) поля NakllD присваивается зна­чение, полученное от встроенной функции GEN_ID. Двумя параметрами обраще­ния к этой функции указывается имя генератора и то значение, на которое должно увеличиться текущее значение генератора («шаг» генератора). В триггерах INSERT и UPDATE можно обращаться к новому значению поля, если его име­ни предшествует предикат NEW, а в триггерах DELETE и UPDATE — к старому зна­чению (предикат OLD).

НЕ нашли? Не то? Что вы ищете?

ВНИМАНИЕ Инициировать автоинкрементные поля с помощью генераторов можно только в триггерах, срабатывающих перед вставкой новой записи.

6.  Аналогичным образом создайте триггеры BEF_INS_FIRMS, BEF_INS_MOVEB BEF_INS_BOOKS, BEF_INS_PAYMENTS для остальных автоинкрементных полей.

7.  Создайте триггер, который перед удалением данных о накладной удаляет данные обо всех связанных с ней книгах:

CREATЕ TRIGGER BEFORE_DEL_NAKLS FOR NAKLS ACTIVE BEFORE DELETE AS

BEGIN

DELETE FROM MoveBook WHERE MNakl = NakllD;

END

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

CREATE TRIGGER BEFORE_DEL_MOVEBOOK FOR MOVEBOOK ACTIVE BEFORE DELETE

AS

/* объявление вспомогательных переменных: */

DECLARE VARIABLE TypeN INTEGER; /* Тип накладной */

DECLARE VARIABLE FirmN INTEGER; /* Шифр партнера */

DECLARE VARIBLE Coeff FLOAT; /* Коэффициент накладной */

BEGIN

/* Помещаем тип накладной в переменную TypeN шифр партнера в

переменную FirmN и коэффициент в Coeff */

SELECT NType, NFirm FROM Nakls WHERE Nakls. NaklID=OLD. MNakl INTO :TypeN, :FirmN;

IF (:TypeN IN (0,3,4,6)) THEN

BEGIN

/* Удаляется книга из накладной, связанной с приходом книг.

Уменьшаем количество книг на складе */

UPDATE Books

SET BQuan=BQuan-OLD. MQuan

WHERE BookID=OLD. MBook;

/* Корректируем сальдо партнера */

IF (:TypeN=4) THEN

/* Увеличиваем обменное сальдо */

UPDATE Firms

SET FChgDelta = FChgDelta+OLD. MQuan*OLD. MPrice*:Coeff

WHERE FirmID=:FirmN; ELSE

/* Увеличиваем финансовое сальдо */

UPDATE Firms

SET FFinDelta = FFinDelta+OLD. MQuan*OLD. MPrice*:Coeff

WHERE FirmID=:FirmN;

END

ELSE

BEGIN

/*Удаляется книга из накладной, связанной с уходом книг. Увеличиваем количество книг на складе */

UPDATE Books SET BQuan=BQuan+OLD. MQuan

WHERE BookID=OLD. MBook;

IF (:TypeN=4) THEN

/*Уменьшаем обменное сальдо */

UPDATE Firms

SET FChgDelta = FChgDelta+OLD. MQuan*OLD. MPrice*:Coeff

WHERE FirmID=:FirmN;

ELSE

/*Уменьшаем финансовое сальдо */

UPDATE Firms

SET FFinDelta= FFinDelta+OLD. MQuan*OLD. MPrice*:Coeff

WHERE FirmID=:FirmN; END END

Многочисленные комментарии поясняют особенности тех или иных действий.

Как видите, в триггерах допускаются локальные переменные и условные операто­ры. Обратите внимание на следующую деталь. Триггер BEFORE_DEL_MOVEBOOK име­ет серьезный недостаток: он не корректирует сумму накладной. Сделано это не случайно. Можно, например, в его начале вставить такие строки: UPDATE Nakls

SET NSum = NSum-OLD. MQuan*OLD. MPrice*:Coeff WHERE NaklID=OLD. MNakl;

Если это сделать, то триггер прекрасно справится с задачей удаления данных о книге из накладной, но попытка удаления всей информации по накладной окажет­ся невозможной, так как триггер будет пытаться изменить поле в удаляемой на­кладной. Как решить эту задачу? Дело в том, что в отличие от процедуры триггеру нельзя передать параметр, который бы указывал на то, что удаляется информация по накладной в целом. Получив такой параметр, триггер просто не стал бы изме­нять сумму накладной, да и коррекцию сальдо партнера можно было бы в этом случае сделать в триггере BEF_DEL_NAKLS сразу для всей суммы, а не делать этого для каждой отдельной книги. Однако повторяю, триггеру нельзя передать пара­метр, а в БД не существует глобальных переменных. Когда я впервые столкнулся с подобной проблемой на практике, она показалась мне неразрешимой. Однако пос­ле некоторого раздумья я нашел, как мне кажется, вполне приемлемое решение. Я добавил в таблицу MOVEBOOK новое поле: ALTER TABLE MOVEBOOK ADD IsDelNakl VARCHAR(l)

Это поле заполняется в процессе ввода значением F в триггере BEF_INS_MOVEBOOK:

CREATE TRIGGER BEF_INS_MOVEBOOK FOR MOVEBOOK BEFORE INSERT AS

BEGIN

NEW. IsDelNakl="F";

NEW. MoveId=GEN_ID(GEN_MOVEBOOK,1);

END

Триггер BEF_DEL_NAKL первым делом выполняет такой оператор:

UPDATE MoveBook SET IsDelNakl="T" WHERE MNakl=OLD. NaklID;

Теперь триггер BEF_DEL_MOVEBOOK может проанализировать это поле и блоки­ровать коррекцию суммы в накладной, если поле содержит Т: IF (OLD. IsDelNakl <> "Т") THEN

UPDATE Nakls

SET NSum = NSum-OLD. MQuan*OLD. MPrice*:Coeff

WHERE NaklID=OLD. MNakl;

Правильные тексты триггеров можно увидеть с помощью SQL Explorer. Для этого раскройте узел рядом с нужной таблицей, затем раскройте узел Triggers, выделите название нужного триггера и перейдите на вкладку Text.

Основные порталы (построено редакторами)

Домашний очаг

ДомДачаСадоводствоДетиАктивность ребенкаИгрыКрасотаЖенщины(Беременность)СемьяХобби
Здоровье: • АнатомияБолезниВредные привычкиДиагностикаНародная медицинаПервая помощьПитаниеФармацевтика
История: СССРИстория РоссииРоссийская Империя
Окружающий мир: Животный мирДомашние животныеНасекомыеРастенияПриродаКатаклизмыКосмосКлиматСтихийные бедствия

Справочная информация

ДокументыЗаконыИзвещенияУтверждения документовДоговораЗапросы предложенийТехнические заданияПланы развитияДокументоведениеАналитикаМероприятияКонкурсыИтогиАдминистрации городовПриказыКонтрактыВыполнение работПротоколы рассмотрения заявокАукционыПроектыПротоколыБюджетные организации
МуниципалитетыРайоныОбразованияПрограммы
Отчеты: • по упоминаниямДокументная базаЦенные бумаги
Положения: • Финансовые документы
Постановления: • Рубрикатор по темамФинансыгорода Российской Федерациирегионыпо точным датам
Регламенты
Термины: • Научная терминологияФинансоваяЭкономическая
Время: • Даты2015 год2016 год
Документы в финансовой сферев инвестиционнойФинансовые документы - программы

Техника

АвиацияАвтоВычислительная техникаОборудование(Электрооборудование)РадиоТехнологии(Аудио-видео)(Компьютеры)

Общество

БезопасностьГражданские права и свободыИскусство(Музыка)Культура(Этика)Мировые именаПолитика(Геополитика)(Идеологические конфликты)ВластьЗаговоры и переворотыГражданская позицияМиграцияРелигии и верования(Конфессии)ХристианствоМифологияРазвлеченияМасс МедиаСпорт (Боевые искусства)ТранспортТуризм
Войны и конфликты: АрмияВоенная техникаЗвания и награды

Образование и наука

Наука: Контрольные работыНаучно-технический прогрессПедагогикаРабочие программыФакультетыМетодические рекомендацииШколаПрофессиональное образованиеМотивация учащихся
Предметы: БиологияГеографияГеологияИсторияЛитератураЛитературные жанрыЛитературные героиМатематикаМедицинаМузыкаПравоЖилищное правоЗемельное правоУголовное правоКодексыПсихология (Логика) • Русский языкСоциологияФизикаФилологияФилософияХимияЮриспруденция

Мир

Регионы: АзияАмерикаАфрикаЕвропаПрибалтикаЕвропейская политикаОкеанияГорода мира
Россия: • МоскваКавказ
Регионы РоссииПрограммы регионовЭкономика

Бизнес и финансы

Бизнес: • БанкиБогатство и благосостояниеКоррупция(Преступность)МаркетингМенеджментИнвестицииЦенные бумаги: • УправлениеОткрытые акционерные обществаПроектыДокументыЦенные бумаги - контрольЦенные бумаги - оценкиОблигацииДолгиВалютаНедвижимость(Аренда)ПрофессииРаботаТорговляУслугиФинансыСтрахованиеБюджетФинансовые услугиКредитыКомпанииГосударственные предприятияЭкономикаМакроэкономикаМикроэкономикаНалогиАудит
Промышленность: • МеталлургияНефтьСельское хозяйствоЭнергетика
СтроительствоАрхитектураИнтерьерПолы и перекрытияПроцесс строительстваСтроительные материалыТеплоизоляцияЭкстерьерОрганизация и управление производством