我有一个触发器:
CREATE TRIGGER tgr_incheck_vlucht
ON PassagierVoorVlucht
AFTER INSERT, UPDATE
AS
BEGIN
IF @@ROWCOUNT= 0 BEGIN RETURN END
SET NOCOUNT ON
BEGIN TRY
IF EXISTS
(SELECT *
FROM inserted I
WHERE EXISTS(SELECT *
FROM PassagierVoorVlucht P inner join Vlucht V on P.vluchtnummer = V.vluchtnummer
WHERE I.inchecktijdstip >= vertrektijdstip))
BEGIN
RAISERROR('Inchecktijdstip moet voor de aankomsttijdliggen', 16,1)
END
END TRY
BEGIN CATCH
IF @@TRANCOUNT > 0 BEGIN ROLLBACK TRANSACTION END
DECLARE @ErrorMessage NVARCHAR(4000) = ERROR_MESSAGE(),
@errorSeverity INT = ERROR_SEVERITY(),
@errorState INT = ERROR_STATE()
RAISERROR (@ErrorMessage, @errorSeverity, @errorState)
END CATCH
END
现在我已经写了一些测试语句:
INSERT INTO PassagierVoorVlucht
VALUES(850, 5316, 1, '2002-01-01 13:37:00.000', 21),
(1002, 5316, 1, '2004-01-01 13:37:00.000', 21),
(1601, 5316, 1, '2004-05-01 13:37:00.000', 21),
(1602, 5316, 1, '2004-05-01 13:37:00.000', 21)
触发器一次仅适用于一个插入行,不适用于整个 block 。我如何编写可以处理多次插入的触发器?
最佳答案
答案是你不能...从根本上来说,触发器是针对每次插入触发的,而不是针对一批代码。这就是为什么它被称为触发器或响应。
此外,如果您的表有一个“插入标识”列,触发器将不会阻止行中出现间隙,因为它们的功能就像序列一样:在行级别并在语句完成后激活(除非 INSTEAD OF)。
MSDN 中的以下内容可能有助于解释触发器:
Although a TRUNCATE TABLE statement is in effect a DELETE statement, it does not activate a trigger because the operation does not log individual row deletions. However, only those users with permissions to execute a TRUNCATE TABLE statement need be concerned about inadvertently circumventing a DELETE trigger this way.
请注意有关单行删除的部分以及有关范围的部分。也许更多地了解您的需求可能会让解决方案变得清晰。
现在,您可以使用 INSTEAD OF
触发器在尝试的代码执行之前触发,但这可能不是一个解决方案,除非您有一些临时表设置或类似的设置功能。而不是替换整个 DML 或 DDL 语句。
如果您希望保护数据的完整性,请考虑使用存储或预先计划的程序。
如果这是 Not Acceptable 或不切实际的,则可以选择其他约束,例如引用键,甚至可以稍后导入的暂存表(取决于数据及时性的需要)。
关于sql-server - 触发处理多个插入,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42609896/