在两列上检查唯一性的有效方法?
Posted
技术标签:
【中文标题】在两列上检查唯一性的有效方法?【英文标题】:Efficient way to CHECK UNIQUE on two columns? 【发布时间】:2014-05-12 03:56:19 【问题描述】:我在 SQL Server 2012 中有一个表,其中包含两个国家/地区的列,我们称它们为 CountryA 和 CountryB。
CREATE TABLE dbo.AgreementParticipants
(
AgreementParticipantsID INT NOT NULL PRIMARY KEY IDENTITY,
CountryA CHAR(3) NOT NULL FOREIGN KEY REFERENCES dbo.Country (CountryCode),
CountryB CHAR(3) NOT NULL FOREIGN KEY REFERENCES dbo.Country (CountryCode)
);
注意:该表已针对示例进行了简化,但重要的是始终定义两个实体之间的双边关系。碰巧在这种情况下是两个国家。
典型数据:
1 AUS USA
2 USA NZL
业务规则:
-
总会有两个县。
这两个国家可以按任意顺序排列。位置 A 或 B 没有意义。
两个国家/地区的每个组合对表来说必须是唯一的。因此,AUS USA 被认为与 USA AUS 相同。
这两个国家永远不会相同。
问题:
执行唯一性约束的最有效方法是什么?
目前,我考虑过使用触发器或复杂的检查约束,但是这两种解决方案都不优雅,所以我希望社区提供一些意见。
【问题讨论】:
【参考方案1】:您可以在两个条件下做到这一点。第一个是唯一索引(或约束):
create unique index AgreementParticipants_CountryA_CountryB on AgreementParticipants(CountryA, CountryB)
第二个是CountryA
小于CountryB
的条件:
check (CountryA < CountryB)
如果国家可能相同,则条件为<=
。
这种方法的一个缺点是,在插入时,CountryA
必须小于 CountryB
(按字母顺序排列)。否则,这会产生错误。
另一种方法使用计算列和唯一索引:
alter table AgreementParticipants
add Country1 as (case when CountryA < CountryB then CountryA else CountryB end);
alter table AgreementParticipants
add Country2 as (case when CountryA < CountryB then CountryB else CountryA end);
create unique index AgreementParticipants_Country1_Country2 on AgreementParticipants(Country1, Country2);
这种方法的优点是可以按任意顺序将国家/地区插入表格中。
【讨论】:
@MarkyMark 。 . .我修改了答案以给出两个解决方案。第一个要求这对是 AUS USA。第二个可以按任意顺序处理对。 谢谢 Gordon,我会试试你的解决方案,看看效果如何。 戈登,我正在检查您的答案,因为它有效并且有我需要的东西。谢谢。【参考方案2】:约束如:
CHECK ( CountryA < CountryB )
UNIQUE ( CountryA, CountryB )
是一种方法
另一种方法是添加计算列,例如:
CREATE TABLE t2 (CountryA ..., CountryB ...
,least_country as LEAST( CountryA, CountryB )
,greatest_country as GREATEST( CountryA, CountryB ) )
然后对新列施加唯一约束。不确定SQLServer是否支持LEAST,如果不支持也很容易创建。
【讨论】:
【参考方案3】:通过为CountryA, CountryB
的每个组合投影一个唯一的“哈希”,可以将 Gordon 的第二个替代方案简化为一个计算列:
ALTER TABLE dbo.AgreementParticipants ADD CountryProjection AS
CASE WHEN CountryA < CountryB
THEN CountryA + '-' + CountryB
ELSE CountryB + '-' + CountryA
END;
ALTER TABLE dbo.AgreementParticipants ADD CONSTRAINT U_AgreementParticipants
UNIQUE (CountryProjection);
SqlFiddle here
【讨论】:
感谢您向我介绍 SQL Fiddle,多么有用的网站!以上是关于在两列上检查唯一性的有效方法?的主要内容,如果未能解决你的问题,请参考以下文章