【问题标题】:Constraint on a group of rows约束一组行
【发布时间】:2021-07-12 13:46:09
【问题描述】:

举个简单的例子,假设我有一个list 表和一个list_entry 表:

CREATE TABLE list 
(
    id SERIAL PRIMARY KEY,
);

CREATE TABLE list_entry 
(
    id SERIAL PRIMARY KEY,
    list_id INTEGER NOT NULL
        REFERENCES list(id)
        ON DELETE CASCADE,
    position INTEGER NOT NULL,
    value TEXT NOT NULL,

    CONSTRAINT list_entry__position_in_list_unique
        UNIQUE(list_id, position)
);

我现在想添加以下约束:具有相同list_id 的所有列表条目都有position 条目,它们形成从1 开始的连续序列。

我不知道怎么做。

我首先想到了EXCLUDE 约束,但这似乎无济于事。

当然可以创建一个触发器,但如果可能的话,我宁愿不这样做。

【问题讨论】:

  • 如果您将此作为约束强制执行,那么删除条目将非常麻烦。

标签: sql postgresql constraints postgresql-9.6 exclusion-constraint


【解决方案1】:

您不能通过约束来做到这一点 - 您需要在代码中实现逻辑(例如,使用触发器、存储过程、应用程序代码等)

【讨论】:

    【解决方案2】:

    我不知道这种使用约束的方式。通常trigger 将是最直接的选择,但如果您想避免使用它们,请尝试使用您即将插入的list_id 获取list_entry 的当前position 编号,例如用list_id = 1 插入list_entry:

    INSERT INTO list_entry (list_id,position,value) VALUES 
    (1,(SELECT coalesce(max(position),0)+1 FROM list_entry WHERE list_id = 1),42);
    

    演示:db<>fiddle

    【讨论】:

    • 像这样更新列表当然不考虑进入位置交换等。
    • @User1291,不,它没有..您的问题中也没有说明:-D 如何维护列表项?可以删除项目或更新职位吗?您是否考虑过使用时间戳而不是整数来维护顺序?
    • 好吧,用户将能够删除任意项目并在任意位置添加新项目......我突然想到我可能会构建一个包含条目的双向链表。尽管将其映射到应用内实体会很痛苦。 XD
    • @User1291 我明白了.. 在那种情况下,我真的认为trigger 可能是最好的选择。您可以轻松地控制从那里插入或更新的内容.. 而且更容易维护;) 欢呼声和快乐的编码。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-03
    相关资源
    最近更新 更多