简体   繁体   English

SQL Server:更新外键引用完整性

[英]SQL Server : updating foreign key referential integrity

I have the following tables in a SQL Server database: A, B & C 我在SQL Server数据库中具有以下表:A,B和C

  • A has a primary key ID A具有主键ID
  • B has a primary key containing ID and A_ID . B有一个包含IDA_ID的主键。 A_ID is also a foreign key to A.ID . A_ID也是一个外键A.ID
  • C has a primary key ID and a foreign key containing A_ID and B_ID C具有主键ID和包含A_IDB_ID的外键

I want to update B and C's A_ID to a different record, eg 我想将B和C的A_ID更新为其他记录,例如

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

Unfortunately due to referential integrity, I won't be able to update B.A_ID. 不幸的是,由于参照完整性,我将无法更新B.A_ID。 If I could, C would have an invalid foreign key. 如果可以的话,C将具有无效的外键。

SQL Fiddle here SQL小提琴在这里

I suppose one way to do this would be to delete the foreign key constraint in C and recreate it after the query has run. 我想做到这一点的一种方法是删除C中的外键约束,并在查询运行后重新创建它。 Is there a way to do this without altering the table structure? 有没有一种方法可以在不更改表结构的情况下执行此操作?

When you want to be able to change the PK of a table that is referenced by a FK, you can, as you mentioned delete and re-create the FK. 当您希望能够更改FK引用的表的PK时,可以如前所述,删除并重新创建FK。

Or you can re-create the FK with ON UPDATE CASCADE . 或者,您可以使用ON UPDATE CASCADE重新创建FK。

This means that if the PK referenced by the FK changes, then the FK will also automatically change. 这意味着,如果FK引用的PK发生更改,则FK也将自动更改。

EDIT: If you mean can you do this without any dropping or altering of the FK at all, then as Rich Brenner suggested in a comment, you can do the "update" in two (four, really) stages, first creating the data you want, and then deleting the data you no longer want: 编辑:如果您的意思是可以完全不降低或更改FK来执行此操作,那么正如Rich Brenner在评论中建议的那样,您可以分两个(四个,实际上)阶段进行“更新”,首先创建数据需要,然后删除不再需要的数据:

  1. Add new desired data to B 向B添加新的所需数据
  2. Add new data to C, referencing new data in B 将新数据添加到C,引用B中的新数据
  3. Delete undesired data from C 从C删除不需要的数据
  4. Delete undesired data from B 从B删除不需要的数据

Unless I'm missing something, why not just use a transaction? 除非我缺少任何东西,否则为什么不使用事务呢?

Since A_Id in both tables points to the Id column in A table, I see no problem to update each table's records in 2 different update statements wrapped in a single transaction. 由于两个表中的A_Id都指向A表中的Id列,因此我认为用单个事务中包装的2个不同的更新语句更新每个表的记录没有问题。 This way, if one of the updates fails, the transaction is rolled back: 这样,如果更新之一失败,则事务将回滚:

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

The foreign key constraints should not pose a problem. 外键约束应该不会造成问题。
see fiddle here. 在这里看小提琴。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM