如何创建确保列具有连续值的约束

时间:2017-07-19 09:57:51

标签: postgresql constraints

我有这个照片模型:

CREATE TABLE photo (
    id serial PRIMARY KEY,
    name text NOT NULL,
    ordinal smallint NOT NULL CHECK (ordinal > 0),
    album integer NOT NULL,
    UNIQUE(name, ordinal, album) DEFERRABLE INITIALLY IMMEDIATE
)

以及一些示例数据

id  name    ordinal  album
1   a.jpg   1        1
2   b.jpg   2        1
3   c.jpg   1        2
4   d.jpg   2        2

照片包含在相册中。在每张专辑中,都会订购照片。

我想创建一个约束,确保ordinal列始终具有连续值。例如,

id  name    ordinal  album
5   e.jpg   4        1

应该被拒绝,因为相册1中没有序数为3的照片。

请注意,我将唯一约束推迟,因为我想允许在相册中重新排序照片。

我也想连续推迟,因为我可能会插入多张照片,所以只要在同一笔交易中插入,就可以插入序号为4的照片,然后再按照序号3插入照片#39 ; t触发错误。

我该如何写这个约束?

我尝试定义一个返回布尔值的函数,并在检查约束中使用它,希望查询表以检查相序是否连续等于当前行中的序数(使用SQL like this )。但postgresql的引用说

  

目前,CHECK表达式不能包含子查询,也不能引用   除当前行的列之外的变量。

所以这似乎是一个死胡同,我不知道如何继续。

有什么想法吗?

1 个答案:

答案 0 :(得分:0)

您可以使用在提交事务期间执行的触发器功能。

见这里:https://stackoverflow.com/a/37277421/1980653

取决于表中的行数,建议实际使用两个触发器:

  1. 一个基于行的常规触发器,用于将触摸记录的ID写入临时表
  2. 延迟的on-commit触发器,在临时表的帮助下,立即检查所有更新的记录。对于每个更新的记录,仍然会调用一次触发器,因此您还应记录检查是否已运行。