【问题标题】:Postgres exclusion constraint on insert/updatePostgres 对插入/更新的排除约束
【发布时间】:2021-07-08 20:31:34
【问题描述】:

我有一个这样定义的表

                               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)

我将如何定义排除约束,以便只有一行具有特定bar_idfoo 能够将approved 设置为true?

例如以下数据:

 foo_id | bar_id | approved 
--------+--------+----------
      1 |      1 | t
      2 |      1 | 
      3 |      2 | 
(3 rows)

我可以将第 3 行的 approved 设置为 true,因为没有其他带有 foo_id 3 的行具有 true 以获得批准。

但是,将第 2 行的 approved 更新为 true 会失败,因为第 1 行也有 foo_id 1 并且已经获得批准。

【问题讨论】:

  • 我认为在你的描述中你混合了 foo_id 和 bar_id - 混淆列名的结果

标签: postgresql triggers constraints exclusion-constraint


【解决方案1】:

您不需要排除约束,过滤的唯一索引就可以了:

create unique index only_one_approved_bar 
   on foo (bar_id)
   where approved;

我还建议将approved 定义为not null。允许 null 值的布尔列通常会导致混淆。

【讨论】:

    【解决方案2】:

    试试这个

    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
    

    【讨论】:

    • 这将不允许多行的批准 = false
    • 添加以回答具有唯一索引和位置的示例。它仅适用于批准为真的行
    猜你喜欢
    • 2020-04-10
    • 2016-12-24
    • 2022-01-17
    • 1970-01-01
    • 2015-04-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-28
    相关资源
    最近更新 更多