触发器处理多个插入

时间:2017-03-05 15:00:34

标签: sql-server sql-server-2008

我有一个触发器:

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)

触发器当时仅适用于一个插入行,而不适用于整个块。如何编写可以处理多个插入的触发器?

2 个答案:

答案 0 :(得分:1)

答案是你不能......从根本上说,每个插入触发了触发器,而不是一批代码。这就是它被称为触发器或响应的原因。

此外,如果您的表具有Insert Identity列,则触发器不会阻止行中的间隙,因为它们的功能就像序列一样:在行级激活并在语句完成后激活(除非INSTEAD OF)。

在MSDN中解释触发器可能有用:

  

{{3}}

     

尽管TRUNCATE TABLE语句实际上是DELETE语句,但它不会激活触发器,因为该操作不会记录单个行删除。但是,只有那些有权执行TRUNCATE TABLE语句的用户才需要担心这种方式无意中绕过DELETE触发器。

请注意有关各行删除的部分以及有关范围的要点。或许更了解您的要求可能会使解决方案更加清晰。

现在,您可以在尝试执行代码之前使用INSTEAD OF触发器触发,但这可能不会成为解决方案,除非您有一些临时表设置或类似的功能。而不是替换整个DML或DDL语句。

  • 如果您希望保护数据的完整性,请考虑使用存储或预先规划的程序。

  • 如果这是不可接受或不切实际的,可以选择其他约束,如参考密钥甚至临时表(取决于对数据的及时性的需要),以后可以导入。

答案 1 :(得分:1)

为此,您需要在触发器内使用一个临时表并将所有插入的数据存储在其中,然后使用while循环对该表进行循环。 这是一个示例,我们希望使用插入触发器

将所有插入的用户添加到审核表中
alter trigger tr_userData_forInsert
on userData
for insert
AS
BEGIN
declare @id int, @name varchar(20)   

select *
into #inserted_data 
from inserted

while ( exists(select id from #inserted_data) )
begin
    select top 1 @id = id, @name = full_name 
    from #inserted_data

    insert into loggs
    values ( concat( 'a user with ',@id, ' and name of ', @name
    , ' is added at ', getdate() ) )

    delete from #inserted_data
    where id = @id
end
end

我已经在多种情况下使用了它,并且效果很好