|
Программирование >> Программирование баз данных
Теперь приступим к созданию обновляемого представления на основе применения триггера 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 Как и следовало ожидать, удаление заказа осуществляется успешно.
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |