【问题标题】:Can a postgres check *conditionally* restrict duplicates?postgres 检查*有条件地*限制重复项吗?
【发布时间】:2012-10-15 11:31:42
【问题描述】:

我必须实施一项规则,即只有一个具有给定 ID 的“组”可以同时具有“进行中”或“问题”状态。是否可以在 Postgres 检查中表示这一点,还是我必须求助于应用程序中的逻辑?

例如:

INSERT INTO group (group_id, status) VALUES (1, 'In Progress'); -- okay
INSERT INTO group (group_id, status) VALUES (2, 'Problem'); -- okay
INSERT INTO group (group_id, status) VALUES (3, 'In Progress'); -- okay
INSERT INTO group (group_id, status) VALUES (4, 'Problem'); -- okay
INSERT INTO group (group_id, status) VALUES (1, 'Something else'); -- okay
INSERT INTO group (group_id, status) VALUES (2, 'Foo bar'); -- okay

INSERT INTO group (group_id, status) VALUES (1, 'In Progress'); -- should fail
INSERT INTO group (group_id, status) VALUES (1, 'Problem'); -- should fail
INSERT INTO group (group_id, status) VALUES (2, 'In Progress'); -- should fail
INSERT INTO group (group_id, status) VALUES (2, 'Problem'); -- should fail

【问题讨论】:

    标签: sql database postgresql duplicates


    【解决方案1】:

    我认为您需要一个部分唯一索引。

    CREATE UNIQUE INDEX group_status_unq_idx 
    ON "group"(group_id, status) WHERE (status IN ('In Progress', 'Problem'));
    

    但是,从您的描述中我不清楚为什么第二个预期失败会失败。对于任何给定的group_id,您是否要只允许In ProgressProblem 之一?如果是这样,您可以编写如下内容:

    CREATE UNIQUE INDEX group_status_unq_idx
    ON "group"(group_id) WHERE (status IN ('In Progress', 'Problem'));
    

    ... 从部分唯一索引中省略 status 并将其仅用于谓词。见this SQLFiddle

    请注意,这不能表示为UNIQUE 约束,因为唯一约束不采用谓词。 PostgreSQL 唯一约束使用一个(非部分)UNIQUE 索引实现,但它也创建了单纯创建索引所没有的元数据条目。部分唯一索引的作用类似于带有谓词的唯一约束,但无法通过元数据(如 information_schema 的约束信息)发现。

    【讨论】:

    • 冒着闲聊的风险:漂亮,漂亮,漂亮!
    • 我想就是这样。谢谢!
    【解决方案2】:

    如果我理解正确:

    create unique index group_restriction_index on group
    (status) where status in ('In Progress', 'Problem')
    

    【讨论】:

      【解决方案3】:

      您可以对多个列进行唯一约束:

      CREATE TABLE group (
          group_id integer,
          status char(100),
          UNIQUE (group_id, status)
      );
      

      (来自Postgresql documentation)。

      这将防止任何状态的重复,而不仅仅是'In Progress''Problem'。我不确定这是否是你想要的。

      【讨论】:

        猜你喜欢
        • 2013-11-21
        • 2020-10-11
        • 2018-02-17
        • 1970-01-01
        • 2020-06-03
        • 1970-01-01
        • 1970-01-01
        • 2017-09-09
        • 2015-07-17
        相关资源
        最近更新 更多