簡體   English   中英

跨多列的唯一值約束

[英]Unique value constraint across multiple columns

假設我有下表:

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

我需要實施以下限制:表中的所有電話號碼(如果有)必須唯一。

即數據庫不應允許以下任何情況:

id | phone1 | phone2
1  | 111    | 111

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

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

我知道如何為前兩個示例實現約束,但是我對第三個示例感到困惑。 有什么辦法嗎?

嘗試一個老把戲:

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

休息會失敗:

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

您不能輕易做到這一點。 least() / greatest()方法並非在所有情況下都適用。

Postgres確實有一些精美的索引操作。 但是最好的方法是使用聯結表。 例如:

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)
);

這還將每個用戶的電話號碼數量限制為2。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM