Postgres中的部分索引

时间:2019-05-15 00:33:05

标签: postgresql constraints database-indexes

在我的一个项目中,我有一个表,其中包含有关某种设备的固件更新的信息。最初,任何固件更新过程都处于ENQUEUED状态。更新过程可能具有其他状态值,例如进行中,已完成,失败。对于单个设备,可能存在状态为COMPLETED和FAILED的多行(更新过程完成,最终状态!)。但是在任何时候,处于入队或进行中状态的每个设备都必须只有一个更新过程-新固件推出仅应针对没有“活动/非最终”更新过程的设备。我试图通过Postgres的部分索引来实现此约束,但是它没有按我预期的那样工作。

这是该表的简化版本:

CREATE TABLE firmware_update_processes
(
    id  uuid DEFAULT uuid_generate_v1(),
    device VARCHAR(10) NOT NULL,
    state VARCHAR (10) NOT NULL DEFAULT 'ENQUEUED',
    PRIMARY KEY (id)
);

这是唯一的部分索引:

CREATE UNIQUE INDEX unique_non_final_firmware_updates_processes
ON firmware_update_processes (device, state)
WHERE state IN ('ENQUEUED', 'ONGOING');

然后我验证了此约束,但是我仍然能够为给定设备插入多个“活动/非最终”更新过程...

INSERT INTO firmware_update_processes (device, state) VALUES ('device1', 'ENQUEUED');
INSERT INTO firmware_update_processes (device, state) VALUES ('device1', 'ONGOING');

是否有(也许是其他方式)在数据库级别完成此任务?任何帮助表示赞赏。

1 个答案:

答案 0 :(得分:2)

我认为应该是:

CREATE UNIQUE INDEX unique_non_final_firmware_updates_processes
ON firmware_update_processes (device)
WHERE state IN ('ENQUEUED', 'ONGOING');

像在以前一样,在(设备,状态)上具有唯一索引,这将明确允许每个设备的已入状态和正在进行状态。由于仅在设备上具有唯一索引,所以我们仅允许每个设备进入“已入队”或“正在进行”状态。