【问题标题】:SQL Update Inserted from Trigger从触发器插入的 SQL 更新
【发布时间】:2020-10-09 15:49:44
【问题描述】:

我正在使用 MS-SQL 我正在尝试创建一个触发器,以使旧文档保持同步。

我在文件顶部有这个声明,它将从没有关联文件路径的公司银行账户中删除文档 ID

UPDATE CompanyBankAccounts
SET SignatureDocumentId = NULL
FROM CompanyBankAccounts cba
INNER JOIN INSERTED i on cba.CompanyBankAccountID = i.CompanyBankAccountID
WHERE (i.SignatureFile IS NULL OR i.SignatureFile = '') 
AND i.SignatureDocumentId IS NOT NULL

但是在我继续做更多依赖于插入表的操作之后,例如

IF (
(SELECT COUNT(*) 
    FROM Inserted i
    LEFT JOIN Documents d on d.documentid = i.SignatureDocumentId
    WHERE (SignatureFile IS NOT NULL AND SignatureFile != '')
    AND ((SignatureFile != d.DocumentPath) OR SignatureDocumentId IS NULL)
) > 0)
BEGIN 
--Do Sync work
END

在初始更新语句之后,插入的行现在仍然有 documentId,有没有办法确保插入的行适当地反映更新所做的更改?

【问题讨论】:

  • 仅供参考 UPDATE CompanyBankAccounts 应该是 UPDATE cba。 SQL Server 应该足够聪明地意识到对CompanyBankAccounts 的新引用是同一个,但这是一个好习惯。
  • @Larnu 谢谢,我不经常写 SQL,所以这些小技巧很有帮助

标签: sql database tsql


【解决方案1】:

来自Docs

插入的表在 INSERT 期间存储受影响行的副本 和 UPDATE 语句。在插入或更新事务期间,新的 行被添加到插入的表和触发器表中。这 插入表中的行是触发器中新行的副本 表。

更新事务类似于删除操作后跟一个 插入操作;旧行首先复制到已删除的表中, 然后将新行复制到触发器表和 插入表格。

“插入”表包含受影响行的副本,其目的是扩展 DML 操作的参照完整性等。因此,它是触发器访问受影响行的正确位置。

【讨论】:

  • 谢谢,我知道插入的行是副本。但是如果我在触发器内部进行更新,那么继续对 INSERTED 进行操作,INSERTED 仍然会不同步。例如,由于它是副本,它仍然包含旧值,我该如何解决?
  • 可以递归调用触发器,并按递归级别逻辑处理它们。你确定要走这条路吗?触发器必须问自己我是什么级别的递归?然后处理它。我建议使用 UPDATE 语句的 OUTPUT 子句重写您的事务并删除触发器。如果需要,然后在循环中运行它
  • 谢谢,我会调查的
  • 如果你添加到问题中,我会试一试
猜你喜欢
  • 1970-01-01
  • 2013-07-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多