SQL Server:禁用正在更新的旧记录的触发器-单行更新有效,多行更新失败

SQL Server:禁用正在更新的旧记录的触发器-单行更新有效,多行更新失败,sql,sql-server,triggers,Sql,Sql Server,Triggers,以下SQL对于单行更新工作正常,但在多行更新时失败: CREATE TRIGGER update_fix ON mytable FOR UPDATE AS BEGIN SET NOCOUNT ON; IF (SELECT f_month FROM inserted) = 99 AND (SELECT x_date FROM mytable WHERE data_id IN ((SELECT data_id FROM inserted)

以下SQL对于单行更新工作正常,但在多行更新时失败:

CREATE TRIGGER update_fix
ON mytable
FOR UPDATE AS
BEGIN
    SET NOCOUNT ON; 

    IF (SELECT f_month FROM inserted) = 99 
       AND (SELECT x_date FROM mytable 
            WHERE data_id IN ((SELECT data_id FROM inserted)))<= DateAdd(yy, -2, GetDate())
    BEGIN
          RAISERROR('Cannot update old records',16,1)
          ROLLBACK TRANSACTION
          RETURN;
    END
END 
GO 
有人能帮我更改触发器,使其适用于影响多行的更新吗?应分别检查每一行的更新情况-因此,如果有10行的更新,其中一行不应更新-则其中一行不会更新,其他行将被成功更新..即使使用触发器,我也无法从大型系统中重新定义查询本身,这样的更改是否超出范围?我担心一个查询=一笔交易。可以全部回滚,也可以全部提交,但是。。可能吧?

使用替代触发器

在触发器中执行更新,并向更新中添加WHERE条件,以便仅更新足够新的行

然后,您可以使用您喜欢的任何逻辑来获取未更新行的行数,并使用RAISERROR发送一条消息,例如5行由于年龄或任何您想要的原因未更新


这样就根本不需要回滚事务。

当然它会失败。对于可以返回多个结果的子查询,您有一个=

if应该如下所示:

if (exists (select 1 from inserted where f_month = 99) and
    exists (select 1
            from mytable
            where data_id in (select data_id from inserted) and
                  x_date <= dateadd(year, -2, getdate())
           )
    )
我不能100%确定这是相同的逻辑,因为这两个条件可能在不同的记录上。现在还不清楚你想要的确切条件是什么

如果两个条件需要在同一记录上,则:

if (exists (select 1
            from mytable
            where data_id in (select data_id from inserted where f_month = 99) and
                  x_date <= dateadd(year, -2, getdate())
           )
    )

那么,您希望在这里得到什么:选择f_month FROM inserted,当您有一个20行的insert并且inserted包含20行时??您可以这样做,但您不能提出一个错误来知道有什么问题,因为正如您所说的,事务要么全部完成,要么什么也不完成。但是,您可以在另一个表中插入错误,并在完成后读取这些错误,但这很难看。我会说,不要使用触发器来验证数据。史蒂夫,你的评论似乎是最终答案。我完全同意在任何触发器中验证这些数据的概念比编码更具黑客性。。我也说到了同一点-似乎使用这个触发器将这些更新记录在一个单独的表中可能比从这些日志处理回程更新更容易…我最后的回答是-这将非常难看。。但是..目前我正在寻找一个快速解决方案,这不一定是非常好的..会看到..无论如何,谢谢大家!您好,谢谢-这很有意义,似乎是我正在寻找的规则尚未测试-此规则应开始后出现错误“无法更新旧记录”,16,1回滚事务返回;结束或其他任何操作以停止仅更新这一行?回滚不会取消查询中的所有更新吗?这就是为什么您使用了一个而不是触发器。然后你必须明确地插入行,否则什么也不会发生。好吧,但是..如果查询不符合规则,我怎么能让它正常释放..据我所知,使用而不是更新方式,我必须为任何可能的更新指定规则..但我不知道特定查询正在更新哪些列..或者我可以正常指定任何其他进程吗?@WebXpert。你必须决定你想要的行为。如果只想更新符合条件的行,则可以这样做。但是,要么触发器引发错误,要么全部失败。或者,它不会引起错误。@Gordon。。。我想让任何查询更新任何超过2年的行,但我想取消任何超过2年的行的更新。。据我所知,到目前为止-问题的核心是一个查询,例如update mytable set mycolumn='myvalue',其中1=1可能会更新一些旧记录和一些新记录-在这种情况下,我希望更新新记录,但旧记录不做任何更改就离开。。