是否可以在具有不同排序规则的2列上创建外键?

时间:2013-07-18 10:12:50

标签: tsql foreign-keys collation

我已经尝试通过所有外键/整理问题搜索大约一个小时但我无法找到甚至远离我的问题的东西。

我有来自两个不同软件供应商的2个表,它们位于同一个数据库中。一个供应商将其排序规则硬编码为Latin1_General_BIN,而另一个供应商使用数据库默认值(在本例中为Latin1_General_CI_AS)。是否可以在不改变任何列的情况下在这两种归类类型之间创建外键?

通常你只需更改一个,但在这种情况下,表格非常敏感,我不允许进行这样的更改,但我必须创建一个外键,因为触发器中的一段逻辑读取这两个表之间的数据只有在找到外键时才会显示:

SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE 
WHERE CONSTRAINT_NAME = 
( 
    SELECT name FROM sys.foreign_keys 
    WHERE parent_object_id = OBJECT_ID( 'Table1' )
    AND referenced_object_id = OBJECT_ID( 'Table2' ) 
)

任何帮助都会非常感激

P.S。我似乎无法弄清楚如果有人帮助我,这个代码的工作原理是什么,我放入了4个必需的空格,但它仍然只是将我的代码显示为文本:(

2 个答案:

答案 0 :(得分:0)

无法将从一个排序规则的字段中的外键约束添加到另一个排序规则的字段。您将收到错误消息1757。

更改其中一个表的排序规则或使用新列创建解决方法,而不是使用正确的排序规则,或使用用于引用的整数创建代理键列。

如果没有其他方法可行且您确实需要修复此类约束并且性能不是问题,请添加检查约束和/或触发器,以检查放入表中的数据的引用完整性。这些规则必须将一个表中的所有值转换为另一个表的排序规则,以便比较值,因此它会很慢,并且使用索引非常棘手,请谨慎行事。

例如,您可以在引用表上有一个插入触发器,用于检查引用的表中是否存在带有插入字符串的记录。然后,您还必须为引用的表添加更新和删除触发器,以使其不会超出引用表中的记录引用的值范围或级联更新/删除。基本上你复制外键是什么,它变得非常慢,并且可怕地扩展。

简短的回答:不要这样做,让桌子保持解开或修复其中一个的整理。

答案 1 :(得分:0)

很好,我认为解决方案非常优雅。我把它写成答案纯粹是因为它是最接近所需解决方案的完全替代方案。但我会将你的答案标记为答案,因为它是正确回答我原来问题的答案。

是的,首先我所做的是,我获得了触发器需要外键的供应商的许可,在其他供应商表的排序规则中,在其表中创建一个新列作为持久计算列:

DECLARE @Collation  nvarchar(100)
DECLARE @SQL        nvarchar(1000)
SET @Collation = ( SELECT collation_name FROM sys.columns WHERE OBJECT_ID IN ( SELECT OBJECT_ID FROM sys.objects WHERE type = 'U' AND name = 'Vendor1Table' ) AND name = 'Vendor1Column' )
SET @SQL = 'ALTER TABLE [Vendor2Table] ADD [Vendor2ComputedColumn] AS [Vendor2Column] COLLATE ' + @Collation + ' PERSISTED'
EXECUTE( @SQL )
GO

接下来,我在计算列中添加了一个候选键:

ALTER TABLE [Vendor2Table] ADD CONSTRAINT [CCUNQ1_x] UNIQUE NONCLUSTERED 
(
    [Vendor2ComputedColumn] ASC
)
WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) 
ON [PRIMARY]
GO

然后,我只是创建了计算列的外键:

ALTER TABLE [dbo].[Vendor1Table]  WITH CHECK ADD CONSTRAINT [CCFOK01_x] FOREIGN KEY ( [Vendor1Column] )
REFERENCES [dbo].[Vendor2Table] ( [Vendor2ComputedColumn] )
GO

ALTER TABLE [dbo].[Vendor1Table] CHECK CONSTRAINT [CCFOK01_x]
GO

最后,原始SQL脚本以漂亮的颜色传递:

SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE 
WHERE CONSTRAINT_NAME = 
( 
    SELECT name FROM sys.foreign_keys 
    WHERE parent_object_id = OBJECT_ID( 'Vendor1Table' )
    AND referenced_object_id = OBJECT_ID( 'Vendor2Table' ) 
)

希望这个小小的演练有一天可以帮助其他人:)

感谢大卫的帮助,感谢它!