【问题标题】: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

业务规则:

  1. 总会有两个县。
  2. 这两个国家可以按任意顺序排列。位置 A 或 B 没有意义。
  3. 两个国家/地区的每个组合对表来说必须是唯一的。因此,AUS USA 被认为与 USA AUS 相同。
  4. 这两个国家永远不会相同。

问题:

执行唯一性约束的最有效方法是什么?

目前,我考虑过使用触发器或复杂的检查约束,但是这两种解决方案都不优雅,所以我希望社区提供一些意见。

【问题讨论】:

    标签: sql sql-server


    【解决方案1】:

    您可以在两个条件下做到这一点。第一个是唯一索引(或约束):

    create unique index AgreementParticipants_CountryA_CountryB on AgreementParticipants(CountryA, CountryB)
    

    第二个是CountryA小于CountryB的条件:

    check (CountryA < CountryB)
    

    如果国家可能相同,则条件为&lt;=。

    这种方法的一个缺点是,在插入时,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 &lt; 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,多么有用的网站!
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-05-27
      • 2011-08-16
      • 1970-01-01
      • 2020-06-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多