【问题标题】:PostgreSQL - next serial value in a tablePostgreSQL - 表中的下一个序列值
【发布时间】:2013-08-16 11:07:29
【问题描述】:

我有一个简单的问题,假设我们有一张桌子:

 id   A   B
 1   Jon  Doe
 2   Foo  Bar

有没有办法知道下一个 id 的增量,在这种情况下是 3 ? 数据库是 PostgreSQL!

Tnx 很多!

【问题讨论】:

  • 其实可以是select MAX(id) FROM the_table)以上的任何东西为什么你想知道?
  • 好吧,我正在从 MySQL 进行 ON DUPLICATE KEY 仿真。它的工作原理是这样的:php 检查我们是否在要保存的对象中有一个 id,如果是,那么好吧,如果没有,从db next id,之后会执行'ON DUPLICATE KEY'查询
  • 嗯。不太清楚。为什么不直接插入没有任何ID的对象,然后查询刚刚使用的ID(从序列中自动弹出)-php.net/manual/en/pdo.lastinsertid.php

标签: postgresql


【解决方案1】:

如果你想认领一个ID并返回它,你可以使用nextval(),它在不插入任何数据的情况下推进序列。

注意,如果这是SERIAL列,则需要根据表和列名找到序列的名称,如下:

Select nextval(pg_get_serial_sequence('my_table', 'id')) as new_id;

无法保证您会看到这些 ID 按顺序返回(序列按顺序生成它们,但多个会话可以声明一个 ID 但尚未使用它,或者回滚一个 INSERT 和ID 不会被重复使用),但可以保证它们是唯一的,这通常是最重要的。

如果你经常这样做而不实际使用 ID,你最终会用完一个 32 位 integer 列的所有可能值(即达到最大可表示整数),但如果你只在有一个很有可能您实际上会插入具有该 ID 的行,应该没问题。

【讨论】:

  • 你能提供There is no cast-iron guarantee of what order these IDs will come back in的来源吗?看起来您提供的 nextval() 链接说的正好相反 - nextval 不能回滚,所以尽管可能存在差距,但下一个 val 将始终是增量的。
  • @TheJKFever 是的,严格来说,他们保证按顺序分发;但是由于您看不到其他事务在做什么,因此从特定代码段内部看起来可能不是那样。例如,如果您连续两次调用nextval,您可能会得到 ID 1 和 5 而不是 1 和 2;或者如果您手动将结果插入到表格中,您可能会发现第 3 行插入在第 2 行之前。我会尝试为该句子想一个更好的措辞。
  • "你最终会用完所有可能的值" - 但这需要很长时间。如果您每周 7 天、每天 24 小时、每秒燃烧 10000 个值,那么“用完”所有值将需要 29247120 年。
  • @a_horse_with_no_name 仅当您使用 64 位 (bigint) 序列时;对于从 1 开始的 32 位序列,例如一个标准的serial 列,该使用率将用完under 3 days 中的所有值。我的实际流程在几周内就用完了范围(但能够安全地进行序列循环,而不是扩大列)。
  • @a_horse_with_no_name 当您尝试将第 2147483649 个值插入列时,这有什么用?如果我将一个序列绑定到一个 32 位值,我希望它的上限为 2^31,因为这是最高可用值。就我而言,内部实现可能是任意精度的算术,它仍然是在我的应用程序中可表示的最高整数,如果我调用nextval 的次数足够多,我就会达到这个限制,并且我会遇到错误。
【解决方案2】:

要获取序列的当前值而不影响它或需要在同一会话中进行先前的插入,您可以使用;

SELECT last_value FROM tablename_fieldname_seq;

An SQLfiddle to test with.

当然,如果有其他同时进行插入的会话,获取当前值将并不能保证您将获得的下一个值实际上是 last_value + 1,因为另一个会话可能已经获取了串行价值摆在你面前。

【讨论】:

  • 请注意,不建议依赖为SERIAL 列生成的序列的命名,因为这被视为实现细节并且可能会更改。 pg_get_serial_sequence() 函数将为您提供特定列“拥有”的序列的名称。
【解决方案3】:

SELECT currval('names_id_seq') + 1;

docs

但是,当然,不能保证它会成为您的下一个价值。如果另一个客户抢在你之前怎么办?您可以为自己保留下一个值,从序列中选择nextval

【讨论】:

  • 你的意思是CURRVAL? Afaik,直到当前会话完成对表的插入后才设置它。
猜你喜欢
  • 2012-11-03
  • 2014-10-08
  • 1970-01-01
  • 2019-09-14
  • 2016-07-22
  • 1970-01-01
  • 1970-01-01
  • 2014-09-05
  • 2020-03-04
相关资源
最近更新 更多