У меня есть таблица, которая содержит записи, которые могут стать частью счета.Я могу сказать, какие из них уже являются частью счета, потому что в таблице есть столбец BillId, который обновляется кодом приложения, когда это происходит.Я хочу запретить обновления любой записи с ненулевым идентификатором BillId.Я думаю, что следующее должно позаботиться об этом:
CREATE TRIGGER [Item_Update_AnyBilled]
ON [dbo].[Item]
FOR UPDATE
AS
BEGIN
SET NOCOUNT ON;
DECLARE @AnyBilled BIT;
SELECT TOP(1) @AnyBilled = 1
FROM inserted i
JOIN deleted d ON i.ItemId = d.ItemId
WHERE d.BillId IS NOT NULL;
IF COALESCE(@AnyBilled, 0) = 1 BEGIN
RAISERROR(2870486, 16, 1); -- Cannot update a record that is part of a bill.
ROLLBACK TRANSACTION;
END;
END;
Однако есть еще одна морщина.В таблице Item также есть столбец DATETIME Modified и триггер, который его обновляет.
CREATE TRIGGER [dbo].Item_Update_Modified
ON [dbo].[Item]
AFTER UPDATE
AS
BEGIN
SET NOCOUNT ON;
UPDATE a
SET Modified = getdate()
FROM Item a JOIN inserted i ON i.ItemId = a.ItemId
END
При наличии этих триггеров добавление элемента в счет всегда вызывает срабатывание RAISERROR.Предположительно потому, что когда заполнен BillId, Item_Update_AnyBilled пропускает его, потому что delete.BillId имеет значение NULL, но затем выполняется Item_Update_Modified, и это вторичное изменение приводит к повторному выполнению Item_Update_AnyBilled, и на этот раз удаленный. BillId больше не равен NULL.1007 *
Как я могу предотвратить обновления таблицы Item, за исключением случая, когда заполняется BillId или когда единственное изменение относится к столбцу Modified?
Я бы предпочел решение, которое не требовало бы, чтобы я сравнивал вставленные и удаленные значения каждого столбца (или использовал COLUMNS_UPDATED ()), поскольку это создало бы проблему обслуживания (кто-то должен был бы забыть обновить)триггер каждый раз, когда новый столбец добавляется или удаляется из таблицы).Я использую SQL Server 2005.