如何获取PostgreSQL序列中的下一个数字

时间:2016-04-02 18:38:53

标签: sql postgresql postgresql-9.4

我正在为PostgreSQL做this。我理解PostgreSQL中的作家不会阻止读者。那么如何安全地增加表中的序列。我知道PostgreSQL有一个序列功能,但我不是在寻找这个,因为我在数据库中创建了数千个序列。

我有一张这样的表:

+----+-----------+------+-------+--+
| id | Part      | Seq  | Model |  |
+----+-----------+------+-------+--+
| 1  | Head      | 0    | 3     |  |
| 2  | Neck      | 1    | 3     |  |
| 3  | Shoulders | 2    | 29    |  |
| 4  | Shoulders | 2    | 3     |  |
| 5  | Stomach   | 5    | 3     |  |
+----+-----------+------+-------+--+

如何为模型3的Stomach之后的下一个seq插入另一条记录。所以这是新表假设的样子:

+----+-----------+------+-------+--+
| id | Part      | Seq  | Model |  |
+----+-----------+------+-------+--+
| 1  | Head      | 0    | 3     |  |
| 2  | Neck      | 1    | 3     |  |
| 3  | Shoulders | 2    | 29    |  |
| 4  | Shoulders | 2    | 3     |  |
| 5  | Stomach   | 5    | 3     |  |
| 6  | Groin     | 6    | 3     |  |
+----+-----------+------+-------+--+

有没有办法制作一个插入查询,它只会在模型3的最高seq之后给出下一个数字。此外,寻找并发安全的东西。

1 个答案:

答案 0 :(得分:1)

您可以使用as关键字在insert语句中查询表。您可以找到完整语法here,但在这种情况下,您需要的语法是insert into <table_name> (<columns...>) <query>

为了确保其他会话无法运行类似的查询,听起来您需要SHARE ROW EXCLUSIVE(SRE)锁定。根据文件:

  

此模式可保护表免受并发数据更改的影响,并且是自包含的,因此一次只能有一个会话保存它。

SRE锁与其他ROW EXCLUSIVE(RE)锁存在冲突,这些锁在任何插入期间获取,但仍允许从表中读取。然而,RE锁本身不会阻止其他会话同时执行插入,因此简单的插入将不足以防止并发更改。

通常通过更改表或创建触发器来自动获取SRE锁,但也可以手动创建。您需要在插入之前获取锁定,然后通过尽快提交更改来释放它。

例如:

begin work;
    lock table my_table in share row exclusive mode;

    insert into my_table
        (id, part, seq, model) as
    select
        max(id) + 1 as id,
        'Next Body Part' as part,
        max(seq) + 1 as seq,
        4 as model
    from
        my_table;
commit work;

需要注意的一点是,这不会阻止应用程序获取最大序列(在上述语句运行之前或同时),然后处理该命令并使用该变量创建新的insert语句。 (例如? as seq,绑定参数为$max_sequence + 1)。为确保它保持并发,您需要确保在同一个insert语句中获取序列号,或者至少在应用程序具有SRE锁定时获取序列号。