|
Программирование >> Sql: полное руководство
Перенос всей нафузки по обеспечению деловых правил на прикладную профам-му имеет ряд недостатков. Дублирование. Если шесть различных профамм осуществляют различные изменения в таблице orders, то каждая из них должна содержать подпрофаммы, обеспечивающие соблюдение деловых правил, касающихся этих изменений. Недостаточная согласованность. Если несколько профамм, написанных разными профаммистами, осуществляют изменения в некоторой таблице, то поддержка деловых правил будет, вероятно, выполняться этими профаммами немного по-разному. Трудность сопровождения. Если деловые правила изменяются, то программисты должны определить все профаммы, в которых реализована поддержка этих правил, найти в них соответствующие места и правильно их модифицировать. Сложность. Часто приходится иметь дело с большим числом деловых правил. Даже профамма для маленькой учебной базы данных, выполняющая обновление заказов, должна учитывать лимиты кредитов, изменять суммы продаж для служащих и офисов, а также изменять имеющееся количество товара. В результате программа, осуществляющая простые обновления таблиц, может очень бысфо стать довольно сложной. Требование стандарта SQL, касающееся того, чтобы поддержку деловых правил осуществляли прикладные профаммы, не является чем-то уникальным. Так было с первых дней появления профамм на языке COBOL и файловых СУБД. Однако много лет существовало постоянное сфемление переложить ответственность за целостность данных на саму базу данных. В 1986 году в СУБД Sybase было введено понятие триггер, что явилось шагом по включению деловых правил в реляционную базу данных. В начале 90-х годов поддержку механизма триггеров начали осуществлять многие реляционные СУБД. Что такое триггер Понятие триггер является относительно простым. С любым событием, вызывающим изменение содержимого таблицы, пользователь может связать сопутствующее действие (фиггер), которое СУБД должна выполнять при каждом возникновении события. Возможны фи таких события, происходящих при попытках изменить содержимое таблицы посредством инсфукций insert, delete и update. Действие, вызываемое событием, задается как последовательность инструкций SQL. Чтобы понять, как работает фиггер, рассмотрим конкретный пример. Когда в таблицу orders добавляется новый заказ, в базу данных необходимо внести еще два изменения: значение в столбце sales для служащего, принявшего заказ, должно быть увеличено на стоимость заказа; имеющееся количество заказываемого товара в столбце qty on hand должно быть уменьшено на заказанное количество единиц товара. Следующая инсфукция диалекта Transact-SQL, используемого в SQL Sener, создает триггер по имени neworder, который вызывает автоматическое выполнение описанных выше изменений: CREATE TRIGGER NEWORDER ON ORDERS FOR INSERT AS UPDATE SALESREPS SET SALES = SALES + INSERTED.AMOUNT FROM SALESREPS, INSERTED WHERE SALESREPS.EMPL NUM = INSERTED.REP UPDATE PRODUCTS SET QTy ON HAND = QTy ON HAND - INSERTED.QTY FROM PRODUCTS, INSERTED WHERE PRODUCTS.MFR ID = INSERTED.MFR AND PRODUCTS.PRODUCT ID = INSERTED.PRODUCT В первой части определения триггера сообщается, что он вызывается всякий раз. когда к таблице orders обращается инструкция insert. В оставшейся части определения (после ключевого слова as) задается действие, выполняемое триггером. В данном случае это действие представляет собой последовательность двух инструкций update; одна для таблицы salesreps, а другая для таблицы products. Ссылка на добавляемую строку делается с помощью имени псевдотаблицы inserted внутри инструкций update. Как видно из этого примера, в SQL Server с целью поддержки триггеров язык SQL был существенно расширен. К другим расширениям, не показанным здесь, относятся проверки if/then/else, циклы, вызовы процедур и даже инструкции print, выводящие сообщения для пользователя Хотя триггеры успешно используются во многих СУБД, они не являются частью стандарта SQL2. Как и в случае со многими другими средствами SQL, взлет популярности которых предшествовал их стандартизации, существуют значительные отличия в плане поддержки триггеров в различных СУБД. Некоторые из этих отличий чисто синтаксические, другие отражают особенности реализации триггеров непосредственно в самой СУБД. Сказанное можно достаточно наглядно продемонстрировать на примере СУБД DB2. Вот определение рассмотренного выше триггера neworder, записанное согласно синтаксису DB2. CREATE TRIGGER NEWORDER AFTER INSERT ON ORDERS REFERENCING NEW AS NEW ORD FOR EACH ROW MODE DB2SQL BEGIN ATOMIC UPDATE SALESREPS SET SALES = SALES + NEW ORD.AMOUNT WHERE SALESREPS.EMPL NUM = NEW ORD.REP; UPDATE PRODUCTS SET QTy ON HAND = QTy ON HAND - NEW ORD.QTY WHERE PRODUCTS.MFR ID = NEW ORD.MFR AND PRODUCTS.PRODUCT ID = NEW ORD.PRODUCT; END Первая часть определения триггера включает те же элементы, которые используются и в SQL Server, только в несколько иной последовательности. Вторая строка явно указывает на то, что триггер вызывается после (after) добавления заказа в базу данных. В DB2 допускается также задавать выполнение триггера непосредственно перед выполнением связанной с ним операции. В данном примере это не имеет смысла, поскольку триггер связан с инструкцией insert, но в случае инструкций update и delete это вполне может потребоваться. Предложение referencing в DB2 задает псевдоним таблицы (new ord), который будет использоваться для ссылки на добавляемую строку в оставшейся части определения триггера. Функционально этот псевдоним аналогичен ключевому слову inserted в SQL Server Ключевое слово new указано потому, что строка добавляется. В случае инструкции delete потребовалось бы указать слово old. Для инструкции update DB2 позволяет указать оба ключевых слова: new (ссылается на таблицу после обновления) и old (ссылается на таблицу перед обновлением). Предложения begin atomic и end окружают набор инструкций, определяющих действие триггера. Две поисковые инструкции update в теле триггера являются простыми модификациями своих аналогов из SQL Server Ссылка на вставляемую строку осуществляется с помощью псевдонима обновленной таблицы, заданного в предложении referencing. Вот еще один пример создания триггера, на этот раз с использованием синтаксиса Informix Universal Server: CREATE TRIGGER NEWORDER INSERT ON ORDERS AFTER (EXECUTE PROCEDURE NEW 0RDER) Этот триггер задает действие, выполняемое после (after) добавления нового заказа. В данном случае набор инструкций, формирующих тело триггера, не указан явно. Все они помещены в хранимую процедуру с именем new order, которая выполняется при запуске триггера. Как показывают эти примеры, хотя базовые концепции механизма триггеров одинаковы в различных СУБД, конкретные детали реализации могут существенно отличаться. Очевидно, сеюдня это одна из наименее стандартизированных частей реляционных баз данных. Триггеры и ссылочная целостность Условия ссылочной целостности, задаваемые внещними и первичными ключами, с помощью триггеров можно реализовать по-иному. Сторонники триггеров указывают на то, что механизм триггеров фактически обеспечивает большую гибкость, чем строгие правила ссылочной целостности, определенные в СУБД DB2 и стандарте ANSI/ISO. Вот пример триггера, реализующего ссылочную целостность для отношения таблиц offices/salesreps, а также отображающего на экране сообщение в случае неуспешной попытки обновления: CREATE TRIGGER REP UPDATE ON SALESREPS FOR INSERT, UPDATE AS IF ((SELECT COUNT(*) FROM OFFICES, INSERTED WHERE OFFICES.OFFICE = INSERTED.REP OFFICE) = 0) BEGIN PRINT Задан неправильный идентификатор офиса. ROLLBACK TRANSACTION Триггеры можно использовать и для обеспечения расширенных форм ссылочной целостности. Первоначально в DB2 с помощью правила cascade обеспечивались каскадные удаления, но не поддерживались каскадные обновления при изменении значения первичного ключа. Однако триггеров это ограничение не касается. Следующий триггер в SQL Server распространяет любое обновление столбца office в таблице offices на столбец rep office таблицы salesreps:
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0.001
При копировании материалов приветствуются ссылки. |