我有3个表tbl_Users
,tbl_Protocol
和tbl_ProtocolDetails
,并且在Users
的触发器内,我必须插入Protocol
然后插入ProtocolDetails
,但我不知道插入范围的工作原理。
类似的东西:
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
答案 0 :(得分:2)
您的触发器有一个 MAJOR 缺陷,因为您似乎总是在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;
至于你的详细信息表,我看到Marc纠正了他的答案,包括多行并有一个简单的解决方案,或者你可以在tbl_Protocol上创建第二个触发器。我过去使用的另一个解决方案是在我有非常复杂的触发器时进行处理的临时表。