【问题标题】:PostgreSQL column values must be in a sequencePostgreSQL 列值必须按顺序排列
【发布时间】:2011-10-22 18:24:09
【问题描述】:

我将如何在 PostgreSQL 中定义一个列,使得每个值都必须在一个序列中,而不是使用类型 serial 时得到的序列,而是一个不能插入值 2 的序列,除非其中已经存在值 1列?

【问题讨论】:

  • 是否允许有间隙?更改列值的删除或更新呢?
  • 这只是理论上的,我想知道如果需要怎么做。但我想说,这样的删除和更新不应该被允许。

标签: sql postgresql sequence restriction


【解决方案1】:

我使用 PL/PgSQL here 编写了一个无间隙序列实现的详细示例。

一般的想法是您想要一个表来存储序列值,然后使用SELECT ... FOR UPDATE 后跟UPDATE - 或简写UPDATE ... RETURNING - 从中​​获取值,同时锁定行直到您的事务提交或回滚。

【讨论】:

    【解决方案2】:

    理论上,您可以使用这样的约束。 (但它在实践中行不通。)

    1. 计算行数。
    2. 评估max(column) - min(column) + 1
    3. 比较结果。

    您可能必须在创建 CHECK 约束之前插入一行。如果没有,max(column) 将返回 NULL。一排,

    1. 计算行数 (1)。
    2. 评估max(column) - min(column) + 1。 (1 - 1 + 1 = 1)
    3. 比较结果。 (1 = 1)

    有 10 行。 .

    1. 计算行数 (10)。
    2. 评估max(column) - min(column) + 1。 (10 - 1 + 1 = 10)
    3. 比较结果。 (10 = 10)

    序列是否从 1 开始无关紧要;如果存在间隙,这种检查方式将始终显示间隙。如果您需要保证无间隙序列从 1 开始,您可以将其添加到 CHECK 约束中。

    据我所知,目前的任何 dbms 都无法以声明方式执行此操作。为此,您需要对CREATE ASSERTION 的支持。 (但我可能是错的。)在 PostgreSQL 中,我认为您对此的唯一尝试涉及多个 AFTER 触发器中的过程代码。

    我只有一张需要无缝的桌子。这是一个日历表。我们每晚运行一次查询来进行这些计算,它让我知道我是否有差距。

    【讨论】:

    • 您可以通过显式锁定来实现。就在INSERT 之前的LOCK TABLE ... IN EXCLUSIVE MODE,所以你可以屏蔽除SELECT 之外的所有内容。
    • 认为关键是声明性约束是否可以保证无间隙序列。 (OP 可能不是那个意思,但这是我的目标。)表上的排他锁可以保证无间隙插入,但这并不完全相同。
    • 啊,有道理。因此,正如您所指出的,它真的可以使用 AFTER 触发器来完成 - 即使那样您也必须依赖触发器排序。
    【解决方案3】:

    您写一个on insert tiggercheck constraint。但是,这仍然允许之后删除“1”并且“2”保留在表中,您可能也必须解决这个问题。

    【讨论】:

    • 我想到了一个检查约束,但我该怎么写呢?
    • 未经测试,应该类似于:... v integer check (v > select max(v) from mytable)check (v = (select max(v) from mytable) + 1)
    • 检查约束不起作用。每一行的检查约束都应该始终为真,这样你在更新时就会遇到问题。
    猜你喜欢
    • 2012-09-16
    • 1970-01-01
    • 2018-11-25
    • 2019-03-12
    • 1970-01-01
    • 2018-12-08
    • 2019-05-10
    • 2019-01-08
    • 1970-01-01
    相关资源
    最近更新 更多