Программирование >>  Программирование баз данных 

1 ... 157 158 159 [ 160 ] 161 162 163 ... 346


Теперь приступим к созданию обновляемого представления на основе применения триггера INSTEAD OF. Для этого необходимо прежде всего определить заранее, какие сценарии должны быть реализованы (в данном случае речь идет только о вставке новьгх строк в таблицу Orderlterns) и какие действия должны быть с этим связаны.

В этом случае мы будем исходить из того, что каждый оператор INSERT, применяемый к представлению, должен рассматриваться как попытка ввести новую позицию заказа. Предположим, что в этом примере строка с данными о клиенте уже существует (при желании можно было бы усложнить задачу и предусмотреть дополнительные условия) и сам заказ с интересующим нас идентификатором OrderlD уже введен. Триггер INSTEAD OF INSERT, предназначенный для решения утсазанной задачи, может выгладеть примерно таким образом:

CREATE TRIGGER trCustomerOrderlnsert ON CustomerOrders vw

INSTEAD OF INSERT

BEGIN

-- Проведение проверки в целях определения того, была ли успешной попытка -- получения строк с помощью оператора INSERT (дело в том, что в конструкции -- WHERE все вставляемые строки могли быть исключены) IF (SELECT COUNT(*) FROM Inserted) > 0 BEGIN

INSERT INTO dbo.Orderltems SELECT i.OrderID,

i.ProductID, i.UnitPrice, i.Quantity FROM Inserted AS i JOIN Orders AS о

ON i.OrderlD = o.OrderlD -- Если бы в таблице Inserted ршелись строки, но не удалось бы создать -- соединение этих строк со строками таблицы заказов, это означало бы, -- что нарушен порядок согласования строк IF @@ROWCOUNT = О

RAISERROR(No matching Orders. Cannot perform insert,10,1)

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

INSERT INTO CustomerOrders vw (

OrderlD,

OrderDate,

ProductID,

Quantity,

UnitPrice

VALUES (

4998-04-06 ,

6.00

в коде триггера явно указано, для какой таблицы предназначены вставляемые данные, поэтому в СУБД SQL Server не возникают какие-либо ошибки. В случае необходимости можно было бы легко дополнить этот пример для решения задачи вставки



данных в другие столбцы, не допускающие NULL-значений, которые не указаны в определении представления (сам клиент не может задавать значения для этих столбцов, поскольку они не определены в представлении, используемом клиентом).

Триггеры INSTEAD OF UPDATE

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

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

Триггеры INSTEAD OF UPDATE, во многом аналогично триггерам INSTEAD OF INSERT, позволяют взять на себя принятие решения о дальнейшей обработке данных и однозначно реализовать это решение. В рассматриваемом примере с обновлением столбца ProductName мы также можем выбрать и тот и другой вариант (изменение названия и смену товара). По умолчанию в такой ситуации СУБД SQL Server обновляет название товара в таблице Products. Но мы можем воспользоваться триггером INSTEAD OF UPDATE, чтобы отменить это решение и явно выполнить поиск в столбце ProductName для определения идентификатора ProductID, если именно в этом состоят намерения пользователя. На основании полученных данных может быть активизирована ошибка, если предоставленное пользователем значение ProductID не совпадает с тем, которое соответствует названию товара.

Триггеры INSTEAD OF DELETE

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

Итак, продолжив пример с представлением CustomerOrders vw, введем некоторые дополнительные функциональные возможности удаления. Но при этом приходится сталкиваться с более значительными сложностями. Предположим, что представление должно применяться для удаления всех строк в каком-то конкретном заказе, но заказ, в котором отсутствуют строки расшифровки, утрачивает свое значение, поэтому возникает необходимость удалить саму строку с заголовком заказа.

По результатам упражнений, выполненных в предьщущем разделе (надеемся, что читатель также в них участвует), в таблицу Order It ems должны быть введены две



строки (одна строка была введена как исходная при создании таблицы, а вторая

вставлена в примере с триггером INSTEAD OF INSERT), но прежде чем приступать

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

CREATE TRIGGER trCustomerOrderDelete ON CustomerOrders vw

INSTEAD OF DELETE

BEGIN

-- Проведение проверки в целях определения того, была ли успешной попытка -- получения строк с помощью оператора DELETE (дело в том, что в конструкции -- WHERE все вставляемые строки могли быть исключены) IF (SELECT COUNT(*) FROM Deleted) > 0 BEGIN

DELETE od

FROM dbo.Orderltems AS oi JOIN Deleted AS d

ON d.OrderlD = oi.OrderlD AND d.ProductID = oi.ProductID DELETE Orders

FROM Orders AS о JOIN Deleted AS d

ON o.OrderlD = d.OrderlD LEFT JOIN Orderltem AS oi

ON oi.OrderlD = d.OrderID AND oi.ProductID = d.OrderlD WHERE oi.OrderlD IS NULL

Перейдем к проведению проверок. Для этого начнем с удаления только одной строки с помощью представления CustomerOrders vw:

DELETE CustomerOrders vw WHERE OrderlD = 1 AND ProductID = 2

После этого еще раз выполним операцию выборки:

SELECT ProductID, UnitPrice, Quantity FROM CustomerOrders vw WHERE OrderlD = 1

Как и следовало ожидать, строка, которая прежде была вставлена в примере, проведенном в разделе с описанием триггера INSTEAD OF INSERT, теперь удалена: ProductID UnitPrice Quantity

1 5.55 3

(1 row(s) affected)

Итак, операция удаления отдельных строк с расшифровкой ааказа выполняется успешно. Теперь попытаемся выполнить более сложные действия, связанные с удалением всего заказа:

DELETE CustomerOrders vw WHERE OrderlD = 1

Чтобы можно было проверить, что операция удаления заказа осуществляется правильно, необходимо полностью перейти к таблице Orders: SELECT * FROM Orders WHERE OrderlD = 1

Как и следовало ожидать, удаление заказа осуществляется успешно.



1 ... 157 158 159 [ 160 ] 161 162 163 ... 346

© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки.
Яндекс.Метрика