简体   繁体   English

跨多列的唯一值约束

[英]Unique value constraint across multiple columns

Suppose, I have the following table: 假设我有下表:

CREATE TABLE "user" (
    id     BIGINT PRIMARY KEY NOT NULL,
    phone1 VARCHAR,
    phone2 VARCHAR
);

And I need to implement the following limitation: all phone numbers (if any) in table must be unique. 我需要实施以下限制:表中的所有电话号码(如果有)必须唯一。

ie database should not allow any of the following situations: 即数据库不应允许以下任何情况:

id | phone1 | phone2
1  | 111    | 111

id | phone1 | phone2
1  | 111    | NULL
2  | 111    | NULL  

id | phone1 | phone2
1  | 111    | NULL
2  | NULL   | 111 

I know how to implement constraints for first two examples, but I'm stuck with the third one. 我知道如何为前两个示例实现约束,但是我对第三个示例感到困惑。 Is there any way to do this? 有什么办法吗?

try an old trick: 尝试一个老把戏:

db=# create unique index on "user" (least(phone1,phone2), greatest(phone1,phone2));
CREATE INDEX
Time: 14.507 ms
db=# insert into "user" values(1,111,111);
INSERT 0 1
Time: 35.017 ms

rest will fail: 休息会失败:

db=# insert into "user" values(2,111,null);
ERROR:  duplicate key value violates unique constraint "user_least_greatest_idx"
DETAIL:  Key ((LEAST(phone1, phone2)), (GREATEST(phone1, phone2)))=(111, 111) already exists.
Time: 10.323 ms
db=# insert into "user" values(2,null,111);
ERROR:  duplicate key value violates unique constraint "user_least_greatest_idx"
DETAIL:  Key ((LEAST(phone1, phone2)), (GREATEST(phone1, phone2)))=(111, 111) already exists.
Time: 5.553 ms
db=# insert into "user" values(1,111,111);
ERROR:  duplicate key value violates unique constraint "user_pkey"
DETAIL:  Key (id)=(1) already exists.
Time: 11.067 ms

You cannot easily do this. 您不能轻易做到这一点。 The least() / greatest() approach will not work in all cases. least() / greatest()方法并非在所有情况下都适用。

Postgres does have some fancy index operations. Postgres确实有一些精美的索引操作。 But the best way is to use a junction table. 但是最好的方法是使用联结表。 For instance: 例如:

create table userPhones (
    userPhoneId bigint primary key ,
    userId bigint references users(id),
    phone_counter int check (phone_counter in (1, 2)),
    phone varchar,
    unique (userId, phone_counter),
    unique(phone)
);

This also limits the number of phone numbers to 2 for each user. 这还将每个用户的电话号码数量限制为2。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM