mysql 中得到新插入数据的 ID ,在 ibatis
中的应用
我们经常有这种需求,插入一条数据库记录时,需要马上得到这条记录的 AUTO_INCREMENT
ID 。很多数据库有内置支持,mysql
中一直没有找到办法,以为没有内置支持呢,所以用个比较笨的办法,有朋友问我这个问题时,我也是说的这个:
select max(ID)
from mytable
返
回最大的 id 。这个语句得与插入记录的语句在同一个“事务”里,如果用 jdbc
事务,应该一个 connection
commit
里。在数据量不大时,应用当然是没有问题。 数据量非常大的情况我就不知道了,我认为应该是没有问题的。因为,一个“事务”就保证了
SQL
插入操作后与 SQL 取得 max(ID)
的操作之间,不可能再有别的数据库操作。 我是这样以为,但还是没有底。。。
今天无意中发现,mysql
还是有内置支持的,有专门的一个函数:LAST_INSERT_ID([expr])
google
这个函数名称,找到英文或者中文的 mysql 参考手册都有详细的说明。文档说明也特别提到,用这个函数得到最新的 id ,操作也还是需要在与插入操作同一个
connection 范围内。应该说与原来的作法是类似的。
还
有一点意外的发现就是,ibatis 里的 sqlmap insert 操作,竟然返回新插入数据的自增
id
。这样我在程序里就不需要用二个独立的方法了,一个 sqlmap insert 就搞定了,真是爽。当然 sqlmap insert
SQL
写法有不同:
<insert
id="insertTopic" parameterClass="topic">
insert into
TOPIC (FORUM_ID, USERID, TITLE, SUMMARY, CREATE_TIME)
values
(#forumId#, #userid#, #title#, #summary#, now())
<selectKey
resultClass="string" keyProperty="id">
select
last_insert_id() as ID from TOPIC limit 1
</selectKey>
</insert>
现在我们来注意一下这行 select last_insert_id() as ID from TOPIC limit
1
,不同的数据库,这地方有不同,都有自己特别的内置实现。请又特别注意
limit
1
这地方,看文档应该是返回一条记录的,就是返回 id 呀,但实际应用中我发现,竟然返回了 n
条记录。没有办法,我只有限制记录条数为 1 ,但结果也是对的。不知道这个算不算 mysql 的 bug 。
如
果大家仔细看
last_insert_id() 这个函数的文档,他举了个用这个函数实现
sequence
的例子,感觉很值得引起注意,暂时我是用不着,但有需要用得着的时候。可能有这样一种需要:需要得到自增 id ,这个
id
我可能是用作数据库表的主键,也可能有别的用途。一般的想法,好像只有在数据库里写个存储过程,反正我是没有写过,关键是需要考虑多用户并发。。。
用 last_insert_id() 函数这样来模拟一个 sequence
实现:
mysql> CREATE TABLE sequence (id INT NOT NULL);
mysql> INSERT INTO sequence VALUES (0);
mysql> UPDATE sequence SET id=LAST_INSERT_ID(id+1);因为“如果
expr
被作为一个参数传递给 LAST_INSERT_ID()
,那么函数将返回这个参数的值,并且被设置为 LAST_INSERT_ID()
返回的下一个值”,这样每次 update sequence 后,id 肯定是自增过了,关键是这个数据库级的支持,不需要你再去考虑多用户并发问题。