【问题标题】:Get next available auto_increment ID in PostgreSQL - A better approach?在 PostgreSQL 中获取下一个可用的 auto_increment ID - 更好的方法?
【发布时间】:2023-03-14 15:50:01
【问题描述】:

我是 postgreSQL 的新手,非常感谢社区提供的任何指点。

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

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

由于文章还没有在数据库中,并且数据库会话尚未开始,我似乎无法使用 postgreSQL 的currval() 功能。此外,如果我使用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;
}

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

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

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

【问题讨论】:

  • 尽快升级到受支持的版本 - 你的版本很古老。
  • 是的,这让我很痛苦。不幸的是,它不是我们拥有的服务器上的站点,升级不是客户的选择。 :(
  • postgresql 7.2?你确定吗?该版本于 2005 年 5 月 9 日停产

标签: postgresql


【解决方案1】:

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

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

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

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

【讨论】:

    【解决方案2】:

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

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

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

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

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

    获取生成的 id

    但同样:您真的应该(我的意思是真的)与客户交谈以升级到 Postgres 的最新版本

    【讨论】:

    • 感谢您的帮助,内容非常丰富。自从提交问题以来,我已按照建议从表 ID 中删除了序列,并实现了一个单独的表,该表包含一个整数,然后我手动递增该整数。它与我所拥有的几乎相同,但它为我省去了重置序列的问题。查看 postgreSQL 手册,似乎在插入触发器在 7.2 中起作用之前,我将对其进行研究,因为它们可能正是我所追求的。
    • @Jeemusu:不,不要那样做!使用与它们的用例完全相同的序列。手动增加值要么不可扩展(由于锁定问题),要么在多用户环境中出错。
    猜你喜欢
    • 1970-01-01
    • 2014-12-10
    • 1970-01-01
    • 2019-11-04
    • 1970-01-01
    • 2016-09-22
    • 2014-07-13
    • 2013-07-27
    • 2011-10-20
    相关资源
    最近更新 更多