我在两个不同的数据库中有两个表。在table1中(在database1中)有一个名为column1的列,它是一个主键。现在在table2(在database2中)有一个名为column2的列,我想将它添加为外键。
我尝试添加它,它给了我以下错误:
Ms 1763,Level 16,State 0,Line 1
不支持跨数据库外键引用。外键Database2.table2。Msg 1750,Level 16,State 0,Line 1
无法创建约束。查看以前的错误。
我是如何做到这一点的,因为这些表位于不同的数据库中。
答案 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完整性的唯一方法是使用触发器。