在两个数据库之间添加外键关系

我在两个不同的数据库中有两个表。 在table1(它在database1中)有一个名为column1的列,它是一个主键。 现在在table2(它在databse2中)有一个名为coulmn2的列,我想把它作为一个外键添加。

我试图添加它,它给了我以下错误:

消息1763,级别16,状态0,行1
跨数据库外键引用不受支持。 外键Database2.table2。

消息1750,级别16,状态0,行1
无法创build约束。 查看以前的错误。

我该怎么做既然这些表在不同的数据库中。

您将需要使用Trigger跨数据库pipe理参照约束。


基本上你创build一个插入,更新触发器来validation主键表中的键的存在。 如果该键不存在,则恢复插入或更新,然后处理该exception。

例:

Create Trigger dbo.MyTableTrigger ON dbo.MyTable, After Insert, Update As Begin If NOT Exists(select PK from OtherDB.dbo.TableName where PK in (Select FK from inserted) BEGIN -- Handle the Referential Error Here END END 

编辑:只是为了澄清。 这不是执行参照完整性的最佳方法。 理想情况下,你会希望两个表在同一个分贝,但如果这是不可能的。 那么上面是一个潜在的工作,为你。

如果您需要坚如磐石的完整性,请将这两个表放在一个数据库中,然后使用FK约束。 如果您的父表在另一个数据库中,则不会阻止任何人从旧备份中还原该父数据库,然后您将拥有孤儿。

这就是为什么不支持数据库之间的FK。

根据我的经验,当相关的两个表的主要权威信息源必须位于两个单独的数据库中时,处理此问题的最佳方法是将表的副本从主位置同步到次位置(使用T- SQL或SSIS进行适当的错误检查 – 当你有一个外键引用的时候,你不能截断和重新填充表,所以有几种方法可以使表更新)。

然后在第二个位置添加一个传统的FK关系到表,这是一个只读的副本。

您可以使用主要位置中的触发器或计划作业来更新副本。

您可以使用用户定义函数的检查约束来进行检查。 它比触发器更可靠。 在必要时可以禁用并重新启用它,并在数据库2恢复后重新检查。

 CREATE FUNCTION dbo.fn_db2_schema2_tb_A (@column1 INT) RETURNS BIT AS BEGIN DECLARE @exists bit = 0 IF EXISTS ( SELECT TOP 1 1 FROM DB2.SCHEMA2.tb_A WHERE COLUMN_KEY_1 = @COLUMN1 ) BEGIN SET @exists = 1 END; RETURN @exists END GO ALTER TABLE db1.schema1.tb_S ADD CONSTRAINT CHK_S_key_col1_in_db2_schema2_tb_A CHECK(dbo.fn_db2_schema2_tb_A(key_col1) = 1) 

简单的答案是,SQL Server(从SQL 2008开始)不支持跨数据库外键 – 如错误消息所述。

虽然您不能具有声明性参照完整性(FK),但您可以使用触发器达到相同的目标。 这是不太可靠的,因为你写的逻辑可能有错误,但它会让你在那里一样。

请参阅SQL文档@ http://msdn.microsoft.com/en-us/library/aa258254%28v=sql.80%29.aspx哪个状态:;

触发器通常用于执行业务规则和数据完整性。 SQL Server通过表创build语句(ALTER TABLE和CREATE TABLE)提供声明性参照完整性(DRI); 但是,DRI不提供跨数据库参照完整性。 为了强制引用完整性(关于表的主键和外键之间的关系的规则),使用主键和外键约束(ALTER TABLE和CREATE TABLE的PRIMARY KEY和FOREIGN KEY关键字)。 如果触发器表上存在约束,则会在执行INSTEAD OF触发器之后和执行AFTER触发器之前检查它们。 如果约束被违反,INSTEAD OF触发器操作被回滚,AFTER触发器不被执行(被触发)。

在SQLTeam上还有一个很好的讨论 – http://www.sqlteam.com/forums/topic.asp?TOPIC_ID=31135

如错误消息所示,这在sql server上不受支持。 确保信息完整性的唯一方法是与触发器一起工作。