【问题标题】:Unique constraints on multiple columns that cannot both be null不能同时为空的多个列的唯一约束
【发布时间】:2019-08-26 15:15:07
【问题描述】:

我想问是否有更好的方法在 Postgres 10 中对以下行为进行建模:

CREATE TABLE test.my_table
(
    id   UUID PRIMARY KEY,
    id_a UUID,
    id_b UUID,
    some_shared_data JSONB,
    UNIQUE (id_a, id_b)
);

CREATE UNIQUE INDEX IF NOT EXISTS b_null_constraint ON test.my_table (id_a) WHERE id_b IS NULL;
CREATE UNIQUE INDEX IF NOT EXISTS a_null_constraint ON test.my_table (id_b) WHERE id_a IS NULL;

ALTER TABLE test.my_table
    ADD CONSTRAINT both_null_constraint CHECK (
        (id_b IS NOT NULL) OR (id_a IS NOT NULL));

即约束是:

  1. id_aid_b 都不能是 null
  2. id_aid_b 的组合必须是唯一的(包括其中之一是 null 的情况)

在我看来,上面设置它的代码不是很有表现力。人们会以另一种/更规范的方式做到这一点吗?我尝试将其拆分为单独的表,但约束 (1.) 很难满足。

【问题讨论】:

  • 这对我来说很好。

标签: sql database postgresql unique-constraint


【解决方案1】:

只需两个unique 约束就可以做到这一点。第二个是:

CREATE UNIQUE INDEX IF NOT EXISTS ab_null_constraint ON my_table ( coalesce(id_a, id_b), (id_a is null) WHERE id_a IS NULL or id_b is null;

Here 是一个 dbfiddle。

实际上,您可以将所有这些组合成一个唯一索引:

CREATE UNIQUE INDEX IF NOT EXISTS ab_null_constraint ON
     my_table ( coalesce(id_a, id_b),
                coalesce(id_b, id_a),
                (id_a is null),
                (id_b is null)
              );

Here 是一个 dbfiddle。

您可能会发现您的原始公式更易于维护。

【讨论】:

  • 感谢您的意见,很高兴获得另一个视角!我认为第二个例子实际上并没有那么糟糕。我对原始解决方案持怀疑态度的一件事是,我发现它使用了许多不同的关键字来表示基本相同的事情。你的解决方案至少可以解决这个问题!我想我更喜欢它:)
  • @Jonas.z 。 . .在索引旁边添加注释,说明您希望它做什么。这并不明显(至少对我而言),我编写了代码。
  • 是的,当然。我发现用严格的文档对这些迁移类型的 sql 文件进行分区很有用。我喜欢你的解决方案是它是对正在发生的事情的封装表达。 IE。我可以把 c​​mets 放在上面直接引用它
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-07-21
  • 1970-01-01
  • 1970-01-01
  • 2012-08-10
  • 1970-01-01
相关资源
最近更新 更多