在概念上是否正确执行SELECT MAX(id)等以查找最后插入的行?

Sco*_*hio 10 mysql sql postgresql

当我发现这个模式用于获取上次插入的行的id时,我正在查看Drupal模块:

SELECT MAX(id) FROM ... WHERE ...
Run Code Online (Sandbox Code Playgroud)

其中id是以通常的自动增量方式工作的字段.

这在概念上是正确的吗?在MySQL/PostgreSQL环境中这种模式会失败的情况吗?

编辑:

感谢您的出色评论和答案!

我应该澄清一下我的问题:我的意思是有人想要找出最后一个插入行的id 而不管会话.

Mat*_*ick 12

这似乎是主观的,但我会说不,这在概念上并不正确,因为:

  • 你想要最近插入的行
  • 但您的查询似乎在最高id

是的,max id和最近的insert之间存在一些关系,但请考虑以下事项:

  • 如果删除最近插入的行怎么办?

回答MySQL:你会得到不同的结果.请注意,甚至不需要多线程或多个进程才能失败.那是因为它们是两个不同的东西(不可否认它们通常可以产生相同的结果).

select max(id) from <tablename>
Run Code Online (Sandbox Code Playgroud)

VS

select last_insert_id()
Run Code Online (Sandbox Code Playgroud)

(猜猜哪一个是对的.)


@Dems指出OP是模棱两可的.我将澄清我的要点:

我们正在讨论三种不同的信息:

  • 最高id
  • id 最近插入的行,特定于会话
  • id 最近插入表中的行(无论会话)

危险的是,有时,查询一个会为另一个人提供正确答案 - 但并非总是如此.

  • OP是否意味着"通过此会话"找到最后插入的记录,或者只是表中的最新记录.这是一个根本不同的问题,我不知道OP在问什么. (2认同)

Mar*_*c B 5

select max(id)仅保证检索具有最高ID的记录.它可能不一定是插入表中的最后记录.请记住,DB操作可以并行运行.您可以插入记录并获取ID#5.但是当你开始做这个时select MAX(id),其他人可能已经插入了另一条记录,现在最大值确实是#6.

同样,您无法使用它来预测下一个分配的ID可能是什么.考虑在事务中完成某些插入的情况.DB中最后提交的记录再次为#5,然后执行3次插入(#6,#7,#8),然后它们被回滚.要执行的下一个插入实际上是#9,而不是#6再次 - mysql不会从失败的事务中回收ID号.并且无法保证你会得到#9 - 其他一些会话可以在你进入之前进行插入,所以你的第四个插入可能是#10,或#10,000,000.