如何在字段顺序无关紧要的情况下实现唯一性

Cri*_*ina 9 sql sql-server primary-key foreign-key-relationship relational-database

我认为以下示例将最好地解释这种情况.假设我们有以下表结构:

-------------------------------------
Member1   int      NOT NULL (FK)(PK)
Member2   int      NOT NULL (FK)(PK)
-------------------------------------
Statust   char(1)  NOT NULL
Run Code Online (Sandbox Code Playgroud)

以下是该表的表格内容:

Member1    Member2    Status
----------------------------
  100        105        A
Run Code Online (Sandbox Code Playgroud)

我的问题是如何实现唯一性,以便下面的INSERT语句将基于表中已有的那一行失败.

INSERT status_table (Member1,Member2,Status) VALUES(105,100,'D');
Run Code Online (Sandbox Code Playgroud)

基本上,我试图模拟两个成员之间的关系.无论我们有(100,105)还是(105,100),状态字段都是相同的.

我知道我可以使用before_insert和before_update触发器来检查表中的内容.但我想知道是否有更好的方法来做到这一点......我的数据库模型应该是不同的......

ype*_*eᵀᴹ 6

如果你能确保所有应用/用户成员的ID存储在至少到最大的顺序(最低MEMBERID在Member1与最大的Member2),那么你可以简单地增加一个检查约束:

ALTER TABLE Status_table
  ADD CONSTRAINT Status_table_Prevent_double_pairs
    CHECK (Member1 < Member2)
Run Code Online (Sandbox Code Playgroud)

如果您不想这样做或者您希望存储额外的信息(因为您正在存储(仅仅是一个示例)"成员100邀请(喜欢,杀死,无论如何)成员150"而不是相反),那么你可以使用@ Tegiri的方法,稍微修改一下(乘以两个足够大的整数会产生溢出问题):

CREATE TABLE Status_table
( Member1 INT NOT NULL
, Member2 INT NOT NULL
, Status CHAR(1) NOT NULL
, MemberOne  AS CASE WHEN Member1 < Member2 THEN Member1 ELSE Member2 END
          --- a computed column
, MemberTwo  AS CASE WHEN Member1 < Member2 THEN Member2 ELSE Member1 END
          --- and another one
, PRIMARY KEY (Member1, Member2)
, UNIQUE (MemberOne, MemberTwo)
, ...                                    --- FOREIGN KEY details, etc 
) ;
Run Code Online (Sandbox Code Playgroud)

  • 而不是同时拥有主键和唯一索引,我不能只创建PrimaryKey(MemberOne,MemberTwo),这将涵盖所有情况? (2认同)