如何从触发器中获取其他表中插入的ID?
问题描述:
我有3个表tbl_Users
,tbl_Protocol
和tbl_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
答
你的触发器有一个主要缺陷的,你似乎期望总是刚刚在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
答
没有什么在这个触发,将处理多重插入/更新语句。您将需要使用一个将处理多个记录的场景,或者使用IF @@ ROWCOUNT = 1 else语句来检查有多少记录受到影响。在你的榜样,我只想用类似
insert into tbl_Protocol(user_id, inserted_date)
select user_id, user_detail + '@' + user_explanation
From INSERTED;
至于您的详细表格,我看到马克纠正了自己的答案,包括了多条线路,并有一个简单的解决方案,也可以创建在tbl_Protocol第二触发器。我过去使用的另一个解决方案是一个临时表,用于处理非常复杂的触发器。
谢谢你的帮助和解释,我不知道这个数据库有这个行为 –