关于使用mysql的 SELECT LAST_INSERT_ID() 语句碰到的问题
程序员文章站
2022-05-29 19:38:17
...
先说下使用mysql 的 SELECT LAST_INSERT_ID()这个sql语句的场景,就是我们向主键是自增的mysql数据表(简称user表)中insert一条记录后,我们期望 获取刚刚写入这条记录的id,因为某些场景下需要获得这个id去做其它的操作,所以很自然的想到了使用SELECT LAST_INSERT_ID() 这个sql语句来获取插入记录后返回的自增id,参考sql语句如下:
<insert id="insert" parameterClass="UserDO">
INSERT INTO user( user_id,user_nick,tel_phone,address,status, user_type,remark, gmt_create, gmt_modified)
VALUES ( #userId#, #userNick#, #telPhone#, #address#, #status#,
#userType#, #remark#, now(), now())
<selectKey keyProperty="id" resultClass="java.lang.Long">
SELECT LAST_INSERT_ID() AS value
</selectKey>
</insert>
其中user表的主键是自增的id.
通过这种方式获取返回的自增id的确大多数情况下的确也能测试通过,所以测试的时候自己也很难发现问题,我就简单说下我碰到的情况:
问题1.有些时候调用Object id=getSqlMapClientTemplate().insert("UserDO.insert", userDO);这个语句返回的id返回的值是0,但是的确记录是写入到数据库user表中去了,这种情况直接导致我用返回值id大于0来判断 insert成功这个逻辑不准备,因为有的时候写入成功了也会返回0,这个问题不是每次都能重现,所以很诡异。
问题2.有些时候调用Object id=getSqlMapClientTemplate().insert("UserDO.insert", userDO);这个语句返回的id返回的值是大于0,但是用这个id去查询user表这条记录时确提示失败,原来是<selectKey keyProperty="id" resultClass="java.lang.Long">
SELECT LAST_INSERT_ID() AS value
</selectKey>
这个语句的意思是返回最后一个写入数据库的id,但是在高并发多个数据表都有写入的情况,下,这个语句返回的就有可能是另外一张表刚刚写入的数据库id,这样根据这个id去查询就返回没有这个记录了
对于以上这两种情况我目前我使用的办法就是insert记录后不根据返回的id值来判断,而是用这个user表的唯一索引user_id去重新查一次user表来获取这个id,这种重新去查的方法基本可以满足大部分场景需求
写这篇文章主要有三个目的:
1.我踩到过这个坑,希望大家引以为鉴,因为测试的时候也比较难发现,希望大家不要犯类似错误
2.对于上面提到的问题1有时候会返回0的情况实在没想通,所以请各位大神帮我扫下盲
3.对于上面提到的解决办法,如果碰到没有设置唯一索引的情况,并且通过多个字段联合查询也不能唯一确定返回的记录是不是就是你刚刚写入的记录的这种情况下,是否有其它的方法可以尝试,在这方面是个新人,求各位大神多多指导!
摘自:http://www.atatech.org/article/detail/14015/0
推荐阅读
-
Mysql查询语句使用select.. for update导致的数据库死锁分析
-
Oracle关于不能直接使用序列到insert select的问题
-
Mysql数据库中的 Order by 语句的特殊之处(select 中的项目不必出现在order by中)---不建议使用!
-
Mysql使用kill命令解决死锁问题(杀死某条正在执行的sql语句)
-
使用最新版MySQL的jdbc驱动关于时区引发的问题
-
关于MySQL安装以及使用的若干常见问题
-
Mysql 使用中碰到的问题记录
-
一个关于php执行mysql语句的有关问题,头都快搞炸,求前辈
-
MySQL笔记:select默认使用不当索引导致的巨大性能损失问题_MySQL
-
linux上,mysql使用聚合函数group by 时报错:SELECT list is not in GROUP BY clause and contains nonaggre的问题