2017-02-16 69 views
1

我有3个表tbl_Userstbl_Protocoltbl_ProtocolDetails和我的触发内部上Users,我一定要插入到Protocol然后插入ProtocolDetails,但我不知道如何工作的插入范围。如何从触发器中获取其他表中插入的ID?

类似的东西:

CREATE TRIGGER tg_Users ON tbl_Users 
AFTER INSERT, UPDATE AS 
BEGIN 
    DECLARE @UserId  = Int 
    DECLARE @ProtocolId = Int 
    DECLARE @UserDetail = NVARCHAR(255) 

    SELECT 
     @UserId = user_id, 
     @UserDetail = user_detail + '@' + user_explanation 
    FROM INSERTED 

    INSERT INTO tbl_Protocol (user_id, inserted_date) 
    VALUES (@UserId, GetDate()) 

    -- Return Inserted Id from tbl_Protocol into @ProtocolDetail then 

    INSERT INTO tbl_ProtocolDetails (protocol_id, protocol_details) 
    VALUES (@ProtocolId, @UserDetail) 
END 

回答

2

你的触发器有一个主要缺陷的,你似乎期望总是刚刚在Inserted表中的一行 - 这是的情况下,由于触发器将被称为每个语句一次(每行不会一次),因此如果一次插入20行,触发器被称为只有一次,而Inserted伪表包含20行。

因此,这样的代码:

Select @UserId = user_id, 
     @UserDetail = user_detail + '@' + user_explanation 
From INSERTED; 

失败,因为你只检索一个(任意)从Inserted表行,你会忽略所有其他行可能在Inserted

编程触发器时需要考虑到这一点!你必须以适当的方式做到这一点,以集合为基础的时尚 - 不是一排排苦恼的排!

试试这个代码:

CREATE TRIGGER tg_Users ON tbl_Users 
AFTER INSERT, UPDATE AS 
BEGIN 
    -- declare an internal table variable to hold the inserted "ProtocolId" values 
    DECLARE @IdTable TABLE (UserId INT, ProtocolId INT); 

    -- insert into the "tbl_Protocol" table from the "Inserted" pseudo table 
    -- keep track of the inserted new ID values in the @IdTable 
    INSERT INTO tbl_Protocol (user_id, inserted_date) 
     OUTPUT Inserted.user_id, Inserted.ProtocolId INTO @IdTable(UserId, ProtocolId) 
     SELECT user_id, SYSDATETIME() 
     FROM Inserted; 

    -- insert into the "tbl_ProtocolDetails" table from both the @IdTable, 
    -- as well as the "Inserted" pseudo table, to get all the necessary values 
    INSERT INTO tbl_ProtocolDetails (protocol_id, protocol_details) 
     SELECT 
      t.ProtocolId, 
      i.user_detail + '@' + i.user_explanation 
     FROM 
      @IdTable t 
     INNER JOIN 
      Inserted i ON i.user_id = t.UserId 
END 
+1

谢谢你的帮助和解释,我不知道这个数据库有这个行为 –

0

没有什么在这个触发,将处理多重插入/更新语句。您将需要使用一个将处理多个记录的场景,或者使用IF @@ ROWCOUNT = 1 else语句来检查有多少记录受到影响。在你的榜样,我只想用类似

insert into tbl_Protocol(user_id, inserted_date) 
select user_id, user_detail + '@' + user_explanation 
From INSERTED; 

至于您的详细表格,我看到马克纠正了自己的答案,包括了多条线路,并有一个简单的解决方案,也可以创建在tbl_Protocol第二触发器。我过去使用的另一个解决方案是一个临时表,用于处理非常复杂的触发器。