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

时间:2010-12-15 16:12:45

标签: sql sql-server tsql foreign-keys

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

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

  

Ms 1763,Level 16,State 0,Line 1
  不支持跨数据库外键引用。外键Database2.table2。

     

Msg 1750,Level 16,State 0,Line 1
  无法创建约束。查看以前的错误。

我是如何做到这一点的,因为这些表位于不同的数据库中。

6 个答案:

答案 0 :(得分:63)

您需要使用Trigger管理跨数据库的引用约束。


基本上,您创建一个insert,update触发器来验证主键表中是否存在Key。如果密钥不存在,则还原插入或更新,然后处理异常。

示例:

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

已编辑:只是为了澄清。这不是强制引用完整性的最佳方法。理想情况下,您可能希望同一个数据库中的两个表,但如果这是不可能的。那么以上就是你的潜在工作。

答案 1 :(得分:35)

如果您需要坚如磐石的完整性,请在一个数据库中同时使用两个表,并使用FK约束。如果您的父表位于另一个数据库中,则没有任何东西阻止任何人从旧备份恢复该父数据库,然后您有孤儿。

这就是不支持数据库之间的FK的原因。

答案 2 :(得分:21)

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

然后在第二个位置将一个传统的FK关系添加到表中,该表实际上是一个只读副本。

您可以在主要位置使用触发器或预定作业来更新副本。

答案 3 :(得分:16)

您可以使用带有用户定义函数的检查约束来进行检查。它比触发器更可靠。它可以在必要时与外键一起禁用和重新启用,并在数据库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)

答案 4 :(得分:3)

简短的回答是SQL Server(从SQL 2008开始)不支持跨数据库外键 - 如错误消息所示。

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

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

  

触发器通常用于强制执行   业务规则和数据完整性。 SQL   服务器提供声明性   参照完整性(DRI)通过   表创建语句(ALTER   TABLE和CREATE TABLE);但是,DRI   不提供跨数据库   参照完整性。执行   参照完整性(有关规则)   小学与小学的关系   表的外键),使用primary   和外键约束(   PRIMARY KEY和FOREIGN KEY关键字   ALTER TABLE和CREATE TABLE)。如果   触发器上存在约束   表,他们检查后   INSTEAD OF触发器执行和先前   到AFTER触发执行。如果   INSTEAD违反了约束条件   触发操作的OF回滚和   AFTER触发器未执行   (烧制)。

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

答案 5 :(得分:0)

正如错误消息所示,sql server不支持此功能。 确保refrerential完整性的唯一方法是使用触发器。