问题描述
Table "public.foo"
Column | Type | Collation | Nullable | Default
----------+---------+-----------+----------+-------------------------------------
foo_id | integer | | not null | nextval('foo_foo_id_seq'::regclass)
bar_id | integer | | |
approved | boolean | | |
Indexes:
"foo_pkey" PRIMARY KEY,btree (foo_id)
Foreign-key constraints:
"foo_bar_id_fkey" FOREIGN KEY (bar_id) REFERENCES bar(bar_id)
我将如何定义排除约束,以便只有一行具有特定 foo
的 bar_id
能够将 approved
设置为 true?
例如以下数据:
foo_id | bar_id | approved
--------+--------+----------
1 | 1 | t
2 | 1 |
3 | 2 |
(3 rows)
我可以将 approved
的第 3 行设置为 true,因为没有其他具有 foo_id
3 的行被批准为 true。
然而,将第 2 行的 approved
更新为 true 会失败,因为第 1 行也有 foo_id
1 并且已经被批准。
解决方法
您不需要排除约束,过滤的唯一索引就可以:
create unique index only_one_approved_bar
on foo (bar_id)
where approved;
我还建议将 approved
定义为 not null
。允许 null
值的布尔列通常是不断混淆的根源。
试试这个
ALTER TABLE public.foo
ADD CONSTRAINT uniq_approved UNIQUE (bar_id,approved)
或者你可以创建唯一索引
CREATE UNIQUE INDEX uniq_approved ON public.foo
USING btree (bar_id,approved)
WHERE approved