`
renjieguixiong5
  • 浏览: 73270 次
  • 性别: Icon_minigender_2
  • 来自: 北京
社区版块
存档分类
最新评论

关于使用mysql的 SELECT LAST_INSERT_ID() 语句碰到的问题

 
阅读更多

   先说下使用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
分享到:
评论
9 楼 Master-Gao 2017-05-09  
legend11 写道
我测试也返回1,搜索了半天,看到这里才恍然大悟:
mapper接口返回值依然是成功插入的记录数,但不同的是主键值已经赋值到领域模型实体的id中了
另:最新的要把resultClass改成resultType


正解啊,从直接理解是错的,加那段代码本质上也不会返回新插入数据的id,返回的还是insert语句执行后受影响的行数,只是会把id赋值到领域模型实体中
8 楼 高军威 2017-01-20  
  最终解决方案呢?
7 楼 legend11 2016-04-24  
我测试也返回1,搜索了半天,看到这里才恍然大悟:
mapper接口返回值依然是成功插入的记录数,但不同的是主键值已经赋值到领域模型实体的id中了
另:最新的要把resultClass改成resultType
6 楼 diuse 2016-04-09  
我也遇到了同样的问题,使用last_insert_id(),返回值有两种,一种是0,一种是插入id-1。没有搞明白是什么原因。后面使用事务包了一下插入就正常了。
我当时是使用id作为了业务主键,插入后必须返回id供用户删除用。
所以返回0或者id-1都不能满足应用。
当时想的另外一种解决方式是自己弄主键,插入只要不报异常就是成功,这样也是比较简单的,麻烦的就是自己控制主键生成
5 楼 kevin2234 2015-10-14  
我跟3楼一样都是返回1,不知道为什么???用4楼的方法还是不行,会报错。求求求解::
4 楼 focus2008 2015-09-17  
要改成这样:
<insert id="insert" parameterClass="UserDO">
<selectKey keyProperty="id" resultClass="java.lang.Long">

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())

SELECT LAST_INSERT_ID() AS value
</selectKey>
</insert>

让 <selectKey> 包含住整个insert 语句:
<selectKey keyProperty="id" resultClass="java.lang.Long">
insert ....
SELECT LAST_INSERT_ID() AS value
</selectKey>
3 楼 wnjustdoit 2015-05-28  
Super_GoodMan 写道
 
可以用以下这种方式,亲测过很好用!
<insert id="add" parameterType="vo.Category" useGeneratedKeys="true" keyProperty="id">
insert into category (name_zh, parent_id,
show_order, delete_status, description
)
values (#{nameZh,jdbcType=VARCHAR},
#{parentId,jdbcType=SMALLINT},
#{showOrder,jdbcType=SMALLINT},
#{deleteStatus,jdbcType=BIT},
#{description,jdbcType=VARCHAR}
)
</insert>

Super_GoodMan 写道
 
可以用以下这种方式,亲测过很好用!
<insert id="add" parameterType="vo.Category" useGeneratedKeys="true" keyProperty="id">
insert into category (name_zh, parent_id,
show_order, delete_status, description
)
values (#{nameZh,jdbcType=VARCHAR},
#{parentId,jdbcType=SMALLINT},
#{showOrder,jdbcType=SMALLINT},
#{deleteStatus,jdbcType=BIT},
#{description,jdbcType=VARCHAR}
)
</insert>


你好,我的每次都返回1,是什么情况呢
2 楼 Super_GoodMan 2015-05-28  
 
可以用以下这种方式,亲测过很好用!
<insert id="add" parameterType="vo.Category" useGeneratedKeys="true" keyProperty="id">
insert into category (name_zh, parent_id,
show_order, delete_status, description
)
values (#{nameZh,jdbcType=VARCHAR},
#{parentId,jdbcType=SMALLINT},
#{showOrder,jdbcType=SMALLINT},
#{deleteStatus,jdbcType=BIT},
#{description,jdbcType=VARCHAR}
)
</insert>
1 楼 zzp1994114 2015-05-27  
挺好,就是需要你这种人

相关推荐

    解决Hibernate JPA中insert插入数据后自动执行select last_insert_id()

    )Hibernate: select last_insert_id()表中有个主键是自增列。可是在以往的项目中,没发现有这样的问题。于是在网上各种找也找不到原因。心想可能是配置问题。 最终在persistence.xml配置文件中找

    PHP获取MySql新增记录ID值的3种方法

    二,使用函数:msyql_insert_id(); 在PHP中,经常需要把插入数据库中的id值取出来,而正好有这么一个函数: 复制代码 代码如下: &lt;?php //执行插入数据库的语句 //…… $getID=mysql_insert_id();//$getID即为最后...

    MySQL 5.1参考手册中文版

    7.2.16. INSERT语句的速度 7.2.17. UPDATE语句的速度 7.2.18. DELETE语句的速度 7.2.19. 其它优化技巧 7.3. 锁定事宜 7.3.1. 锁定方法 7.3.2. 表锁定事宜 7.4. 优化数据库结构 7.4.1. 设计选择 7.4.2. 使你的...

    MySQL 5.1参考手册

    7.2.16. INSERT语句的速度 7.2.17. UPDATE语句的速度 7.2.18. DELETE语句的速度 7.2.19. 其它优化技巧 7.3. 锁定事宜 7.3.1. 锁定方法 7.3.2. 表锁定事宜 7.4. 优化数据库结构 7.4.1. 设计选择 7.4.2. 使你的数据尽...

    易语言批量sql解析为数组, SQL终结符解析

     SELECT LAST_INSERT_ID();[/font]。以上问题还有, 字符串中包含单引号就需要用两个单引号表示....实在不想屈服于前面两种蛋疼的方式, 试着自己封装子程序解析, 忽略字符串什么的. 有时候脑子是个好东西, 可惜我...

    mysql数据库的基本操作语法

    constraint fk_classes_id foreign key(classes_id) references classes(id) ); 多列外键组合,必须用表级别约束语法: create table classes( id int, name varchar(20), number int, primary key(name, number) ...

    MYSQL中文手册

    7.2.16. INSERT语句的速度 7.2.17. UPDATE语句的速度 7.2.18. DELETE语句的速度 7.2.19. 其它优化技巧 7.3. 锁定事宜 7.3.1. 锁定方法 7.3.2. 表锁定事宜 7.4. 优化数据库结构 7.4.1. 设计选择 7.4.2. 使你...

    mysql官方中文参考手册

    7.2.16. INSERT语句的速度 7.2.17. UPDATE语句的速度 7.2.18. DELETE语句的速度 7.2.19. 其它优化技巧 7.3. 锁定事宜 7.3.1. 锁定方法 7.3.2. 表锁定事宜 7.4. 优化数据库结构 7.4.1. 设计选择 7.4.2. 使你的数据尽...

    MYSQL常用命令大全

    mysql&gt; select * from MyClass order by id limit 0,2; 或者: mysql&gt; select * from MyClass limit 0,2; 6、删除表中数据 命令:delete from 表名 where 表达式 例如:删除表 MyClass中编号为1 的记录 mysql&gt; ...

    MySQL5.1参考手册官方简体中文版

    7.2.16. INSERT语句的速度 7.2.17. UPDATE语句的速度 7.2.18. DELETE语句的速度 7.2.19. 其它优化技巧 7.3. 锁定事宜 7.3.1. 锁定方法 7.3.2. 表锁定事宜 7.4. 优化数据库结构 7.4.1. 设计选择 7.4.2. 使你的数据尽...

    mysql5.1中文手册

    INSERT语句的速度 7.2.17. UPDATE语句的速度 7.2.18. DELETE语句的速度 7.2.19. 其它优化技巧 7.3. 锁定事宜 7.3.1. 锁定方法 7.3.2. 表锁定事宜 7.4. 优化数据库结构 7.4.1. 设计选择 ...

    2009达内SQL学习笔记

    如:select last_name,dept_id from s_emp where dept_id in(41,42);第41、42部门的人 like : 包含某内容的。模糊查询 可以利用通配符创建比较特定数据的搜索模式,通配符只能用于文本,非文本数据类型不能使用...

    MySQL命令大全

    mysql&gt; select * from MyClass order by id limit 0,2; 或者: mysql&gt; select * from MyClass limit 0,2; 6、删除表中数据 命令:delete from 表名 where 表达式 例如:删除表 MyClass中编号为 的记录 mysql&gt;...

    MYSQL,SQLSERVER,ORACLE常用的函数

    SQL&gt; select last_day(sysdate) from dual; LAST_DAY(S ---------- 31-5月 -04 38.MONTHS_BETWEEN(date2,date1) 给出date2-date1的月份 SQL&gt; select months_between('19-12月-1999','19-3月-1999') mon_...

    SQL培训第一期

    select l.OBJECT_ID,s.SID,s.SERIAL#,s.USERNAME, s.MACHINE from V$locked_Object l,V$session s where l.SESSION_ID = s.SID; 2.1.6.2 解锁 alter system kill session 'sid,serial#'; 2.1.7 备份与恢复 2.1.7.1 ...

    oracle学习文档 笔记 全面 深刻 详细 通俗易懂 doc word格式 清晰 连接字符串

    例如:INSERT(插入)、UPDATE(修改)、DELETE(删除)语句  数据查询语言 (Data Query Language, DQL) 是SQL语言中,负责进行数据查询而不会对数据本身进行修改的语句,这是最基本的SQL语句。例如:SELECT(查询...

    txtSQL 文本数据库类

    TXTSQL是一种文本数据库,文件存储方式类似mysql,兼容部分sql语句. ... ... ...  ...  $sql = new txtSQL('./data');... echo "最后插入ID号:".$sql-&gt;last_insert_id('table1') ;  $sql-&gt;disconnect();  ?&gt;

    易语言-易语言批量sql解析为数组, SQL终结符解析

     SELECT LAST_INSERT_ID();[/font] 以上问题还有, 字符串中包含单引号就需要用两个单引号表示.... 实在不想屈服于前面两种蛋疼的方式, 试着自己封装子程序解析, 忽略字符串什么的. 有时候脑子是个好东西, 可惜我...

Global site tag (gtag.js) - Google Analytics