INSERT
当我对具有列的表执行单行时,AUTO_INCREMENT
我想使用该LAST_INSERT_ID()
函数返回AUTO_INCREMENT
为该行存储的新 'ed 值。
毫无疑问,许多 Microsoft SQL Server 开发人员和管理员都知道 SQL Server ( SCOPE_IDENTITY
and @@IDENTITY
) 中的等效功能并非没有问题。
我知道 MySQL 文档状态:
生成的 ID 在每个连接的基础上维护在服务器中。这意味着函数返回给给定客户端的值是为影响该客户端列的
AUTO_INCREMENT
最近语句生成的第一个值。此值不会受到其他客户端的影响,即使它们生成自己的值。这种行为确保每个客户端都可以检索自己的 ID,而不用担心其他客户端的活动,也不需要锁或事务。AUTO_INCREMENT
AUTO_INCREMENT
甚至说:
从多个客户端同时使用
LAST_INSERT_ID()
和AUTO_INCREMENT
列是完全有效的。
是否存在任何可能导致LAST_INSERT_ID()
无法返回正确值的已知风险或场景?
我在 CentOS 5.5 x64 和 Fedora 16 x64 以及 InnoDB 引擎上使用 MySQL 5.5。
我想在使用时指出一些注意事项
LAST_INSERT_ID
:我知道您提到了单行插入。但是在进行多行插入时,
LAST_INSERT_ID()
将返回插入的第一行(不是最后一行)的值。如果插入失败,
LAST_INSERT_ID()
将是未定义的。对于事务的自动回滚(由于错误)也是如此。如果您在成功的事务中执行插入,并且您仍然发出
ROLLBACK
,LAST_INSERT_ID()
将保持回滚之前的状态。在使用和基于语句的复制时有几个注意事项。第一个是在触发器或函数中使用时。第二个是不太常见的情况,您的 auto_increment 列是复合主键的一部分,而不是键中的第一列。
AUTO_INCREMENT
LAST_INSERT_ID
要进一步扩展 DTest 给出的答案中的第 2 点:
在我使用的 MySQL 版本中,最好在您计划执行插入的每个代码块之前明确重置 LAST_INSERT_ID 的值。
这可以这样做:
上面这一系列语句执行完后,你可以通过在执行结束时检查 LAST_INSERT_ID 是否仍然设置为“some_flag_init_value_of_your_choice”来知道插入是否有任何影响。
否则,您可能会遇到以下有问题的情况:
因为第二次插入失败,您可能期望第二次调用 LAST_INSERT_ID 将返回 NULL 或生成空结果集(零行)。它仍然返回一个有效的整数标识符这一事实可能会误导您认为第二个插入成功,而实际上它没有。
当您考虑到 LAST_INSERT_ID 将继续保留并重复上一个成功的唯一 id 时,事情会变得更糟,即使后续失败的插入语句针对的表与生成最后一个成功的唯一 id 的表不同。换句话说,你插入到表 TA 并得到一个 id 为 5,然后你插入到 TB 中(但它失败了),但你仍然看到一个 5。基于此,你认为你刚刚在 TA 中创建了一个新行id 为 5 , TB 中有一个新行,id 为 5,而实际上,TB 中不存在任何 id 为 5 的行,或者确实存在这样的行,但它实际上与您刚才的任何代码无关跑了。