【问题标题】:How to create a constraint that ensures a column has continuous values如何创建确保列具有连续值的约束
【发布时间】:2017-07-20 05:24:56
【问题描述】:

我有这个模型用于照片:

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 不应该触发错误。

我应该如何写这个约束?

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

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

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

有什么想法吗?

【问题讨论】:

    标签: postgresql constraints


    【解决方案1】:

    您可以使用将在事务提交期间执行的触发器函数。

    请看这里:https://stackoverflow.com/a/37277421/1980653

    根据表中的行数,建议实际使用两个触发器:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-05-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-09-06
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多