【问题标题】:SQL Server : updating foreign key referential integritySQL Server:更新外键参照完整性
【发布时间】:2016-05-16 13:30:41
【问题描述】:

我在 SQL Server 数据库中有以下表:A、B 和 C

  • A有一个主键ID
  • B 有一个包含IDA_ID 的主键。 A_ID 也是 A.ID 的外键。
  • C 有一个主键ID 和一个包含A_IDB_ID 的外键

我想将 B 和 C 的 A_ID 更新为不同的记录,例如

UPDATE B SET A_ID = 2 WHERE ID = 1
UPDATE C SET A_ID = 2 WHERE B_ID = 1

很遗憾,由于参照完整性,我无法更新 B.A_ID。如果可以的话,C 会有一个无效的外键。

SQL Fiddle here

我想这样做的一种方法是删除 C 中的外键约束并在查询运行后重新创建它。有没有办法在不改变表结构的情况下做到这一点?

【问题讨论】:

  • 您的数据模型意味着来自A 的多重继承。您能否重构您的表格设计,以便 C 不引用 A 考虑是否已经引用 B
  • 不,我无法更改表格设计。
  • 你能解释一下 C 上的 FK 吗?如果没有将 A_ID 和 B_ID 都作为主键的表,它如何“包含”这两者?
  • 好点。哎呀……我的错。 B 有主键 ID 和 A_ID 我会更新我的问题。
  • 我刚刚遇到了类似的问题。您能否结合插入和选择来创建实际上重复的数据,这样您就不会遇到完整性问题,更新子表,然后删除您不需要的原始数据?

标签: sql sql-server database


【解决方案1】:

当您希望能够更改 FK 引用的表的 PK 时,您可以如您所述删除并重新创建 FK。

或者您可以使用ON UPDATE CASCADE 重新创建 FK。

这意味着如果FK引用的PK发生变化,那么FK也会自动变化。

编辑:如果您的意思是您可以在不删除或更改 FK 的情况下执行此操作,那么正如 Rich Brenner 在评论中建议的那样,您可以在两个(四个,真的)阶段,首先创建您想要的数据,然后删除您不再需要的数据:

  1. 将新的所需数据添加到 B
  2. 向 C 中添加新数据,在 B 中引用新数据
  3. 从 C 中删除不需要的数据
  4. 从 B 中删除不需要的数据

【讨论】:

  • 谢谢 Tab,虽然我确实说过“有没有办法在不改变表结构的情况下做到这一点?”我的意思是我不想改变外键。我不确定是否有更好的方式可以这么说。
  • 我建议:1.将新数据添加到B,2.更新c中的数据,3.从B中删除旧数据。然后只需3步
【解决方案2】:

除非我遗漏了什么,否则为什么不直接使用事务呢?

由于两个表中的A_Id 都指向A 表中的Id 列,因此我认为在包含在单个事务中的两个不同的更新语句中更新每个表的记录没有问题。 这样,如果其中一个更新失败,事务就会回滚:

BEGIN TRY
BEGIN TRANSACTION

UPDATE b 
SET a_id = 3 
WHERE id = 3;

UPDATE c
SET a_id = 3
WHERE b_Id = 3;

COMMIT TRANSACTION

END TRY
BEGIN CATCH
    IF @@TRANCOUNT > 0
        ROLLBACK TRANSACTION
END CATCH

外键约束应该不会造成问题。
see fiddle here.

【讨论】:

  • 谢谢佐哈尔。 SQLFiddle 非常有用……我以前没见过。不幸的是,您提供的架构并不完全符合我的意图。我会更新我的问题以澄清事情。另外,如果我理解正确,SQL 的 try catch 部分会回滚事务,而不是显示发生的异常:sqlfiddle.com/#!6/89736/3
  • 现在我明白你的意思了。显然我的建议在这种情况下不起作用。选择 Tab 的答案。无论如何,对于以后的问题,请提供相关的表(s)ddl语句,以避免这样的误解。
  • 当然,我以后会这样做。谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-07-30
  • 1970-01-01
相关资源
最近更新 更多