在PostgreSQL中获取下一个可用的auto_increment ID-更好的方法?

Jee*_*usu 5 postgresql

我是PostgreSQL的新手,因此非常感谢社区提供的任何指导。

我正在更新一个刚继承的旧站点的CMS中的某些功能。基本上,在将文章插入数据库之前,我需要它的ID。无论如何,在数据库会话(插入)开始之前,是否仍要检查序列将使用的下一个值?

起初我以为可以使用SELECT max(id) from tbl_name,但是由于id是从序列中自动递增的,并且文章通常会被删除,因此显然不会为序列中的下一个值返回正确的id。

由于本文尚未在数据库中,并且数据库会话尚未启动,因此似乎无法使用currval()postgreSQL 的功能。此外,如果使用nextval()它,则在插入数据之前会自动递增序列(插入也会自动递增序列,最终导致序列加倍)。

目前,我的解决方法如下:

function get_next_id()
{
    $SQL = "select nextval('table_id_seq')";
    $response = $this->db_query($SQL);
    $arr = pg_fetch_array($query_response, NULL, PGSQL_ASSOC);

    $id = (empty($arr['nextval'])) ? 'NULL' : intval($arr['nextval']);
    $new_id = $id-1;
    $SQL = "select setval('table_id_seq', {$new_id})";
    $this->db_query($SQL);

    return $id;
}
Run Code Online (Sandbox Code Playgroud)

SELECT nextval('table_id_seq')用来获取序列中的下一个ID。随着序列的增加,我立即使用它SELECT setval('table_id_seq',$id)来将序列设置回其原始值。这样,当用户提交数据并且代码最终命中INSERT语句时,它将自动递增,并且插入之前和插入之后的ID相同。

虽然这对我有用,但我对postgreSQL不太热衷,想知道它是否会导致任何问题,或者它们是否不是更好的方法?没有自动递增的序列就没有办法检查序列的下一个值吗?

如果有帮助,我正在使用PostgreSQL 7.2

use*_*810 5

各位 - 在插入记录之前获取 ID 是有原因的。例如,我有一个应用程序,它将 ID 存储为插入另一个字段的文本的一部分。只有两种方法可以做到这一点。

1)无论采用哪种方法,在插入之前获取ID以包含在我的INSERT语句中
2)INSERT,获取ID(再次,无论如何(SELECT ...或来自INSERT ... RETURNING id;)),更新包含 ID 的记录的文本字段

许多评论和答案都假设OP做错了什么......这是......错误的。OP 明确指出“基本上,我需要一篇文章的 ID,然后才能将其插入数据库”。OP为什么想要/需要这样做并不重要- 只需回答问题即可。

我的解决方案选择预先获取 ID;所以我根据需要执行 nextval() 和 setval() 来实现我需要的结果。


小智 2

免责声明:不确定 7.2,因为我从未使用过它。

显然,您的 ID 列被定义为从序列中获取其默认值(可能是因为它被定义为serial虽然我不知道这在 7.x 中是否可用)。

如果删除默认值但保留序列,则可以nextval()在插入新行之前检索下一个 ID。

删除列的默认值将要求您在插入期间始终提供 ID(通过从序列中检索它)。如果你无论如何都这样做,那么我不认为有什么问题。如果您想满足这两种情况,请创建一个插入前触发器(7.x 有吗?)来检查 ID 列是否有值,如果没有从序列中检索新值,否则就不要管它。

但真正的问题是:为什么在插入之前需要 ID。您可以简单地将行发送到服务器,然后通过调用获取生成的idcurval()

但再说一遍:你真的应该(我的意思是真的)与客户交谈以升级到最新版本的 Postgres

  • @Jeemusu:不,不要那样做!使用完全符合其用途的序列。手动递增值要么不可扩展(由于锁定问题),要么在多用户环境中**将**出错。 (4认同)