使用 SQL Server 触发器在插入后更新另一个表中的列

awd*_*Boy 3 sql sql-server triggers

我正在尝试使用 SQL Server 触发器完成以下操作:将新行插入到表中后,我想更新另一个表中的列。

例如:我有一个名为Users的表和一个名为Activity. 每次客户端连接到服务器时,都会在Activity表中插入一行;一旦插入行(其中包含user_id),我想更新Users表中存储上次活动的日期和时间的列。

UPDATE Users
SET Last_Activity_TimeStamp = GETDATE()
WHERE Users.User_ID = Activity.User_ID
Run Code Online (Sandbox Code Playgroud)

但是 SSMS 抛出一个错误说:

无法绑定多部分标识符“dbo.Activity.User_ID”

如果我将上述更新语句更改为:

UPDATE Users
SET Last_Activity_TimeStamp = GETDATE()
WHERE Users.User_ID = User_ID
Run Code Online (Sandbox Code Playgroud)

用户表中的所有行都被更新。

我知道有一个Inserted表,并且在将行插入到主Activity表之前将行添加到那里,但是我可能有很多用户连接并且将有很多行插入到Activity表中。每秒可能达到 1000 个。我想知道如何获得user_id该行被插入到Activity表和更新Last_Activity_TimeStampUsers表。

编辑:我想我缺乏知识的地方是我不知道Inserted任何时候表中可以有多少行,因为在我的设计中,单个事务仅插入一行。Inserted由于有多个用户连接和断开连接,因此表中是否可能有来自其他活动事务的不止一行?

任何帮助将不胜感激!

谢谢

mar*_*c_s 5

其他响应都没有考虑到Inserted触发器中的伪表有时会包含多行- 一个人永远不应该选择单个值 -如果一次插入多行,这将不会按预期工作

触发必须写基于集合的方式来处理这种情况-这真的很简单-尝试是这样的:

CREATE TRIGGER trgActivityInsert
ON [dbo].[Activity]
FOR INSERT
AS
BEGIN
    UPDATE u
    SET Last_Activity_TimeStamp = GETDATE()
    FROM dbo.Users u
    INNER JOIN Inserted i ON u.User_Id = i.User_Id
END
Run Code Online (Sandbox Code Playgroud)

有了这个,无论您一次插入一行、十行还是一百行,您的触发器都可以正常工作,并且表中的所有相应条目dbo.User都将正确更新。

  • 太好了,我已经设法做了一些测试,你是绝对正确的。我唯一要补充的是,正如上面有人发布的那样,似乎插入表的范围仅限于触发器,并且由于设计上我只为每个用户的每个活动插入一行(永远不会更多),因此它将只包含一行。不过话虽如此,你的方法确实是最可靠的方法,因此我将采用它。非常感谢! (2认同)