用外键 (RI) 替换创建触发器

Posted

技术标签:

【中文标题】用外键 (RI) 替换创建触发器【英文标题】:Replace Create Trigger with Foreign Key (RI) 【发布时间】:2012-01-16 09:28:26 【问题描述】:

创建触发器:

SELECT @oldVersionId = (SELECT DISTINCT VERSION_ID FROM Deleted)
    SELECT @newVersionId = (SELECT DISTINCT VERSION_ID FROM Inserted)
    SELECT @appId = (SELECT DISTINCT APP_ID FROM Deleted)

UPDATE [TableName]
SET [VERSION_ID] = @newVersionId
WHERE (([VERSION_ID] = @oldVersionId) AND ([APP_ID] = @appId) )

可以用外键替换此触发器以更新 VERSION_ID 吗?

我认为可能存在问题的是 AND 条件,如何在具有 On del/update Cascade 的 FK 中表达它?

【问题讨论】:

我想摆脱那个触发器并用 FK 约束替换它。当 PK ID 更改级联时,另一个 FK ID 表上的更改。 【参考方案1】:

外键约束不更新任何内容。它们检查正在写入记录的值,如果它们导致约束失败,则会导致写入失败。

另外,正如@marc_s 在他的评论中指出的那样,MS SQL Server 中的触发器是基于设置的。 INSERTEDDELETED 表可以同时保存多条记录。您的代码仅适用于一条记录。

你可以尝试这些方法......

UPDATE
  table
SET
  VERSION_ID = inserted.VERSION_ID
FROM
  table
INNER JOIN
  deleted
    ON  table.VERSION_ID = deleted.VERSION_ID
    AND table.APP_ID     = deleted.APP_ID
INNER JOIN
  inserted
    ON deleted.PRIMARY_KEY = inserted.PRIMARY_KEY

编辑

我刚刚看了你的评论,我想我明白了。你想要一个带有ON UPDATE CASCADE 的外键约束。

您使用这种格式通过 DDL 创建它。

ALTER TABLE DBO.<child table>
ADD CONSTRAINT <foreign key name> FOREIGN KEY <child column>
REFERENCES DBO.<parent table>(<parent column>)
ON [DELETE|UPDATE] CASCADE

或者您可以只使用 SQL Server Management Studio 来设置它。只需确保 ON UPDATE CASCADE 存在即可。

【讨论】:

【参考方案2】:

我无法真正告诉你你在寻找什么——你的问题太不清楚了。

但基本上,如果两个表是通过外键约束链接的,当然你可以添加一个子句来确保父表的 PK 更改时子表得到更新:

ALTER TABLE dbo.ChildTable
ADD CONSTRAINT FK_ChildTable_ParentTable
FOREIGN KEY(ChildTableColumn) REFERENCES dbo.ParentTable(PKColumn)
   ON UPDATE CASCADE

ON UPDATE CASCADE 正是这样做的——如果引用的列(ParentTable 中的 PKColumn)发生变化,那么 FK 约束将“级联”更新到子表并更新它的 ChildTableColumn 以匹配新的PKColumn

阅读 all about cascading referential integrity constraints 以及您在 MSDN 联机丛书中有哪些选择

【讨论】:

以上是关于用外键 (RI) 替换创建触发器的主要内容,如果未能解决你的问题,请参考以下文章

android sqlite 如何设置外键

请问sqlserver中的两个表怎么进行关联

Spring用外键保存复合主键

如何在运行时使用 Oracle 环境中的触发器和/或过程创建外键

mysql级联更新的两种方式:触发器更新和外键

在mysql中创建两个用外键链接的表,插入、删除和更新