關於觸發器的使用,有很多爭議。
觸發器的好處不言而喻是增強了數據的校驗能力,能夠有效地實現復雜的業務邏輯。在一定程度上走的比約束和check走的更遠。
關於觸發器的壞處,最典型的就是觸發器的使用會導致系統性能下降,數據的不可控性,尤其是跨表檢測,以及可能導致的觸發器遞歸更加加深了數據的維護難度和不可控性。
本文無意討論觸發器的原理和好壞,旨在描述一個關於批量數據提交時的觸發器是如何設計的。
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_NULLS ON
GO
CREATE TRIGGER [TRI_xxx] ON xxx
FOR INSERT,UPDATE
AS
SET NOCOUNT ON
DECLARE
--檢測標志設置
@CHECK INT,
--定義公共變量
@TODAY DATETIME
--定義基表變量
@fIEld1 INT,
@fIEld2 INT,
@fIEld3 VARCHAR(20),
@fIEldN INT,
--定義跨表變量
@table1_fIEld1 INT,
@table1_fIEld2 INT,
@tableN_fIEldM INT
--定義游標
DECLARE cur_xxx CURSOR FOR
SELECT field1,field2,field3,fIEldN FROM INSERTED
--如果非集合修改,則定義為如下
/*
SELECT @field1=fIEld1,
@field2=fIEld2,
@field3=fIEld3,
@field4=fIEld4,
FROM INSERTED
*/
SET @TODAY=CONVERT(VARCHAR(10),GETDATE(),120)
OPEN CUR_ZYGD
FETCH NEXT FROM cur_xxx INTO @field1,@field2,@field3,@fIEldN
WHILE (@@FETCH_STATUS=0)
BEGIN
------------------------------------------------------------------------
--------------------以下針對不同的規則,進行相關處理--------------------
------------------------------------------------------------------------
--滿足某某條件,則不處理直接退出
IF cond1
BEGIN
CLOSE cur_xxx --非游標,無需該語句
DEALLOCATE cur_xxx --非游標,無需該語句
RETURN
END
--滿足某某條件,則提示處理直接退出
IF cond2
BEGIN
RAISERROR('XXX錯誤!',16,1)
ROLLBACK TRAN
CLOSE cur_xxx --非游標,無需該語句
DEALLOCATE cur_xxx --非游標,無需該語句
RETURN
END
--跨表檢查,滿足某某條件,則提示處理直接退出
SELECT TOP 1 @table1_field1=fIEld1 FROM table1 WHERE 1=1
IF cond3 IS NOT NULL
BEGIN
RAISERROR('XXX錯誤!',16,1)
ROLLBACK TRAN
CLOSE cur_xxx --非游標,無需該語句
DEALLOCATE cur_xxx --非游標,無需該語句
RETURN
ELSE
BEGIN
SET @field1=@table1_fIEld1 --可能會根據其他跨表的結果更新當前值
END
--最後根據主鍵更新相關值
UPDATE xxx
SET field1=@fIEld1,
field2=@fIEld2
WHERE PrimaryKey=@PrimaryKey AND (ISNULL(field1,'')<>ISNULL(@field1,'') OR ISNULL(field2,0)<>ISNULL(@fIEld2,0))
FETCH NEXT FROM cur_xxx INTO @field1,@field2,@field3,@fIEldN
END
CLOSE CUR_xxx
DEALLOCATE CUR_xxx
SET NOCOUNT OFF
GO
SET QUOTED_IDENTIFIER OFF
GO
SET ANSI_NULLS ON
GO