次の表でフラグの値が1の場合、列のフラグ(更新可能)を除くすべての列の更新を防ぐために、トリガーのヘルプが必要です。
CREATE TABLE Tmp (Id INT, Type INT, TranDate DATE, Flag INT)
INSERT INTO Tmp VALUES (1, 2, '2017-04-24', 0)
INSERT INTO Tmp VALUES (2, 4, '2017-04-27', 1)
以下のコードで試しましたが、正しく動作しません。
CREATE TRIGGER [dbo].[Prevent_Update_Trigger]
ON [dbo].[Tmp]
FOR UPDATE
AS
SET NOCOUNT ON
IF EXISTS(SELECT NULL FROM dbo.Tmp t JOIN inserted i ON t.Id=i.Id AND t.Flag=1)
BEGIN
RAISERROR('You can not update when Flag value is 1', 16, 1)
ROLLBACK TRAN
SET NOCOUNT OFF
RETURN
END
SET NOCOUNT OFF
CREATE TRIGGER dbo_Tmp_trg_AU
ON dbo.Tmp
AFTER UPDATE
AS
BEGIN
SET ROWCOUNT 0;
SET NOCOUNT ON;
IF EXISTS
(
SELECT NULL
FROM Deleted AS Del
WHERE
-- Originally, flag was 1
Del.Flag = 1
AND NOT EXISTS
(
-- Column(s) aside from Flag have changed
SELECT
Del.[Type],
Del.TranDate
INTERSECT
SELECT
Ins.[Type],
Ins.TranDate
FROM Inserted AS Ins
WHERE
-- Same Id
Ins.Id = Del.Id
)
)
BEGIN
RAISERROR ('You can not update when Flag value is 1', 16, 1);
ROLLBACK TRANSACTION;
RETURN;
END;
END;
これは、Id
列を更新できないことを前提としています(たとえば、IDENTITY
列です)。
コードをこれに変更すれば動作します。私はそれをテストしました。
CREATE TRIGGER [dbo].[Prevent_Update_Trigger]
ON [dbo].[Tmp]
FOR UPDATE
AS
SET NOCOUNT ON
IF EXISTS(SELECT NULL FROM dbo.Tmp t JOIN deleted i ON t.Id=i.Id AND i.Flag=1)
BEGIN
RAISERROR('You can not update when Flag value is 1', 16, 1)
ROLLBACK TRAN
SET NOCOUNT OFF
RETURN
END
SET NOCOUNT OFF
テスト:
UPDATE tmp SET flag=10
WHERE id =2
エラーメッセージ:
Msg 50000, Level 16, State 1, Procedure Prevent_Update_Trigger, Line 8 [Batch Start Line 20] You can not update when Flag value is 1 Msg 3609, Level 16, State 1, Line 21 The transaction ended in the trigger. The batch has been aborted.