Использование триггера INSTEAD OF для обновления представления
Пересказ статьи Chad Callihan. Using INSTEAD OF Trigger to Update View
Недавно я столкнулся со странной проблемой, и мне подумалось, что это может стать отличным постом в блоге. Мне сообщили о стандартном процессе в приложении, который завершался неудачно со следующей ошибкой SQL:
Msg 4405, Level 16, State 1, Line 19
View or function ‘XXXXX’ is not updatable because the modification affects multiple base tables.
(Представление или функция не является обновляемым, поскольку модификация затрагивает несколько базовых таблиц.)
Я понимал смысл этой ошибки, но был сбит с толку появлением ее в этом конкретном случае. Я обновлял или модифицировал это представление множество раз ранее, так что происходит?
После некоторых исследований, сравнений и головной боли я обнаружил, что это конкретное представление не имело триггеров, которые обычно присутствуют, чтобы позволить выполняться обновлениям. Как только я воссоздал обычные триггеры, в частности триггер на обновление, все заработало.
Давайте рассмотрим небольшой пример, использующий триггер INSTEAD OF для обновления представления.
Сначала мы создадим пару таблиц с именами героя и злодея:
Давайте начнем с этой знаменитой пары:
И добавим представление, чтобы видеть их вместе:
Что если мы захотим, чтобы нашей первой парой были Superman и Lex Luthor, а не Batman и Joker? Если мы попытаемся выполнить оператор обновления, то получим ошибку:
Как нам обойти эту ошибку? Одним из решений является добавление триггера INSTEAD OF UPDATE. Мы будем использовать этот триггер для замены героя и злодея новыми героем и злодеем:
Теперь мы снова можем выполнить наше обновление и увидеть, что изменения произошли:
Наше обновление теперь прошло успешно, и мы можем видеть наших новых соперников:
Давайте рассмотрим небольшой пример, использующий триггер INSTEAD OF для обновления представления.
Добро или зло
Сначала мы создадим пару таблиц с именами героя и злодея:
CREATE TABLE Hero (
Id INT PRIMARY KEY
,H_Name VARCHAR(20) NOT NULL
);
CREATE TABLE Villain (
Id INT PRIMARY KEY
,V_Name VARCHAR(20) NOT NULL
);
Давайте начнем с этой знаменитой пары:
INSERT Hero VALUES (1,'Batman');
INSERT Villain VALUES( 1,'Joker');
И добавим представление, чтобы видеть их вместе:
CREATE VIEW Rivals
AS
SELECT h.*
,v.V_Name
FROM Hero h
JOIN Villain v ON h.id = v.id;
Что если мы захотим, чтобы нашей первой парой были Superman и Lex Luthor, а не Batman и Joker? Если мы попытаемся выполнить оператор обновления, то получим ошибку:
UPDATE Rivals
SET H_Name = 'Superman'
,V_Name = 'Lex Luthor'
WHERE Id = 1;
GO
Msg 4405, Level 16, State 1, Line 19
View or function ‘Rivals’ is not updatable because the modification affects multiple base tables.
(Представление или функция ‘Rivals’ не является обновляемым, поскольку модификация влияет на несколько базовых таблиц.)
Человек из стали
Как нам обойти эту ошибку? Одним из решений является добавление триггера INSTEAD OF UPDATE. Мы будем использовать этот триггер для замены героя и злодея новыми героем и злодеем:
CREATE TRIGGER InsteadRivals ON Rivals
INSTEAD OF UPDATE
AS
BEGIN
UPDATE h
SET h.H_Name = i.H_Name
FROM INSERTED i
JOIN Hero h ON i.Id = h.Id
PRINT 'Updated Hero Table'
UPDATE v
SET v.V_Name = i.V_Name
FROM INSERTED i
JOIN Villain v ON i.Id = v.Id
PRINT 'Updated Villain Table'
END
GO
Теперь мы снова можем выполнить наше обновление и увидеть, что изменения произошли:
UPDATE Rivals
SET H_Name = 'Superman'
,V_Name = 'Lex Luthor'
WHERE Id = 1;
GO
Наше обновление теперь прошло успешно, и мы можем видеть наших новых соперников:
SELECT * FROM Rivals;
GO
Обратные ссылки
Автор не разрешил комментировать эту запись
Комментарии
Показывать комментарии Как список | Древовидной структурой