我在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
业务规则:
问题:
实施唯一性约束的最有效方法是什么?
目前,我考虑使用触发器或复杂的检查约束,但这两种解决方案都不合适,所以我希望得到社区的一些意见。
答案 0 :(得分:3)
您可以使用两个条件执行此操作。第一个是唯一索引(或约束):
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);
这种方法的优点是可以按任何顺序将国家/地区插入表格。
答案 1 :(得分:1)
约束如:
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,但如果不支持,则很容易创建一个。
答案 2 :(得分:1)
通过投射一个独特的“哈希”,可以将戈登的第二个替代方案简化为一个计算列。 CountryA, CountryB
的每个组合:
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);