0

我已经尝试在所有外键/排序规则问题中搜索大约一个小时,但我什至找不到与我的问题很接近的东西。

我有来自两个不同软件供应商的 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' ) 
)

任何帮助将不胜感激

PS如果有人能帮助我,我似乎无法弄清楚这段代码是如何工作的,我输入了4个必需的空格,但它仍然只是将我的代码显示为文本:(

4

2 回答 2

0

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

要么更改其中一个表的排序规则,要么使用新列创建一个变通方法,以使用正确的排序规则,或者使用用于引用的整数创建代理键列。

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

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

简短的回答:不要这样做,让表格保持松散状态或修复其中一个的排序规则。

于 2013-07-18T11:55:25.803 回答
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' ) 
)

希望这个小演练有一天能帮助其他一些人:)

感谢大卫的帮助,不胜感激!

于 2013-07-18T13:54:38.213 回答