【问题标题】:Create a composite key创建复合键
【发布时间】:2017-04-07 06:59:03
【问题描述】:

我有一张这样的桌子:

Id   PersonId     Phone   IsPrimary
-----------------------------------
1     1          12345        1
2     1          55555        0
3     2          66666        1
4     3          77777        1
5     3          88888        0
6     3          99999        0

我如何创建一个约束,允许每个 PersonId 仅插入一个 IsPrimary = 1 到该表中。对于所有 PersonId,应该只有一个 IsPrimary = 1。因此,我将无法插入下一条记录:

  Id   PersonId     Phone   IsPrimary
  -----------------------------------
  1     1          00000        1

【问题讨论】:

  • 一种方法是只允许通过stored procedure 更新此表。您可以使用 SP 来执行您的业务逻辑。
  • 在插入期间创建一个代替触发器将允许您在插入值之前检查此条件

标签: sql-server tsql composite-key


【解决方案1】:

您可以尝试创建一个唯一的过滤索引:

CREATE UNIQUE INDEX UQ_Person_isPrimary
ON Person (PersonId, IsPrimary)
WHERE IsPrimary = 1

【讨论】:

  • 不知道 SQL Server 有这个,我只以为 Oracle 有。你知道第一个版本是什么吗?
  • @RaduGheorghiu 这是 SQL Server 2008。
  • 也不知道,+1。
  • 这是一个我不知道的非常酷的功能,但我觉得在这种情况下,它只是一种掩盖不良桌子设计的方法。很好的答案,但对于提出问题的人来说可能不是最好的建议(对于这样一个简单的问题来说有点矫枉过正)。
【解决方案2】:

您正在尝试使用数据而不是实际关系在两个实体之间创建关系。每个人都有一个主要电话号码和多个非主要电话号码。而不是使用数据描述主要电话号码关系(在您的情况下,IsPrimary 列),它应该是 Persons 表中的外键:

Persons table
=============

PersonId   Name      PrimaryPhoneId
-----------------------------------
1          Alice     1
2          Bob       3
3          Charlie   4



Phones table
============

Id   PersonId   Phone
---------------------
1    1          12345
2    1          55555
3    2          66666
4    3          77777
5    3          88888
6    3          99999

这样,一个人只能拥有一部主要手机。此外,如果有人切换了他们的主要电话号码,您只需更新一行。如果您持有 IsPrimary 列,则必须更新两行(将旧主设置为 0,然后将新主设置为 1),并确保两个更新发生在同一个事务中,否则您可能会丢失如果第二行无法更新,则完全是主要的。

【讨论】:

    【解决方案3】:

    过滤索引!

    CREATE UNIQUE NONCLUSTERED INDEX uniquey_thingumyjig
      ON table_name (PersonId)
        WHERE  IsPrimary = 1
    

    https://msdn.microsoft.com/en-us/library/ms188783.aspx

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-07-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-04-12
      • 2016-05-08
      • 1970-01-01
      相关资源
      最近更新 更多