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

时间:2012-06-13 05:48:10

标签: postgresql

我是postgreSQL的新手,所以非常感谢来自社区的任何指示。

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

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

由于该文章尚未在数据库中,并且数据库会话尚未启动,似乎我无法使用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。随着这增加序列I,然后立即使用SELECT setval('table_id_seq',$id)将序列设置回原始值。这样,当用户提交数据并且代码最终命中INSERT语句时,它会自动递增,插入前和插入后的ID相同。

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

如果它有助于我使用postgresql 7.2

2 个答案:

答案 0 :(得分:3)

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

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

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

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

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

获取生成的 ID

但是又一次:你应该(我的意思是真的)与客户谈谈升级到最新版本的Postgres

答案 1 :(得分:3)

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

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

许多评论和答案都假设OP做错了什么......这是错误的。 OP明确指出“基本上,我需要在将文章插入数据库之前将其标识为”。 OP 为什么 OP想要/需要这样做也无关紧要 - 只需回答这个问题。

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