SQL Server触发器可将更新的行复制到另一个历史表

时间:2018-08-07 01:33:57

标签: sql sql-server triggers

基本上我想将所有已更新的行复制到另一个SQL历史记录表中,但要附加“版本”列

CREATE TRIGGER [dbo].TriggerName 
ON [dbo].[Users] 
AFTER UPDATE 
AS
BEGIN
    SET NOCOUNT ON;

    INSERT INTO [dbo].[UsersHistory] ([AspNetUserId], [CreditCustomerId],
                                      [UserName], [GivenNames], [Surname],
                                      [Email], [PhoneNumber], [Active],
                                      [Administrator], [AutomaticSuspension],
                                      [CurrentVersion], [Version], [Notes],
                                      [LastUpdateId], [LastUpdateDate])
        SELECT 
            Id, CreditCustomerId, 
            UserName, GivenNames, Surname, 
            Email, PhoneNumber, Active, 
            Administrator, AutomaticSuspension,
            1,
            (SELECT ISNULL(MAX(VERSION) + 1, 1) 
             FROM [dbo].AspNetUsersHistory
             WHERE AspNetUserId = (SELECT Id from DELETED)),
            Notes,
            0, GETDATE()
        FROM 
            DELETED
END

如果这样做,我会在下面出现错误

  

子查询返回了多个值。当子查询遵循=,!=,<,<=,>,> =

时,不允许这样做

基本上,我想为每个用户更新版本列,因此每当用户更改详细信息时,它应该为1,2或3。

3 个答案:

答案 0 :(得分:1)

更改

(SELECT ISNULL(MAX(VERSION) + 1, 1) from [dbo].AspNetUsersHistory
WHERE AspNetUserId = (SELECT Id from DELETED)),

(SELECT ISNULL(MAX(VERSION) + 1, 1) from [dbo].AspNetUsersHistory
WHERE AspNetUserId = deleted.ID),

不需要(从已删除的ID中选择)-这是一个子查询,它可以直接看到正在处理的父行。


编辑后添加

要更新记录的所有先前版本以将CurrentVersion设置为false,请将其置于插入上方的触发器内-它应首先运行

UPDATE UH SET CurrentVersion = 0
FROM dbo.[UsersHistory] UH
    INNER JOIN deleted D on D.Id = UH.[AspNetUserId]
WHERE UH.CurrentVersion <> 0;

答案 1 :(得分:0)

您需要记住,特殊表Deleted将不仅包含一行,而且包含触发更新语句一部分的完整行集。因此,如果您在一条语句中更新10行,则DELETED表中将包含10行。这是您的WHERE AspNetUserId = (SELECT Id from DELETED))失败的地方。我倾向于将它们全部带有时间戳记写在历史记录表中,如果以后需要转换为版本号,请稍后使用查询。用这种方式完成的版本号总是有问题的。

答案 2 :(得分:0)

您不应在派生表中再有一条SELECT语句。只需使用SELECT语句中的ID,如下所示:

INSERT INTO [dbo].[UsersHistory] ([AspNetUserId], [CreditCustomerId],
                                      [UserName], [GivenNames], [Surname],
                                      [Email], [PhoneNumber], [Active],
                                      [Administrator], [AutomaticSuspension],
                                      [CurrentVersion], [Version], [Notes],
                                      [LastUpdateId], [LastUpdateDate])
SELECT 
            Id, CreditCustomerId, 
            UserName, GivenNames, Surname, 
            Email, PhoneNumber, Active, 
            Administrator, AutomaticSuspension,
            1,
            (SELECT ISNULL(MAX(VERSION) + 1, 1) 
             FROM [dbo].AspNetUsersHistory
             WHERE AspNetUserId = d.Id),
            Notes,
            0, GETDATE()
        FROM 
            DELETED as d;