在某些状况下咱们须要向数据表中更新一条记录的状态,而后再把它取出来,但这时若是你在更新前并无一个确认唯一记录的主键就没有办法知道哪条记录被更新了。html
举例说明下:mysql
有一个发放新手卡的程序,设计数据库时常见的方案有两种:sql
方案一:使用一张表,新手卡和领取记录都在一块儿,这样主要字段就是新手卡(主键)、用户ID(唯一)、领取状态(非必要)等数据库
这样的话数据库操做就简单了,直接一条update sql,将用户id更新到这张表里,而后根据用户ID再select出来就行了。但这样记录不少时就会有效率的问题,暂不讨论。并发
方案二:使用两张表,一张存放新手卡,另一张存放领取记录。新手卡表里面有新手卡(主键)、新手卡状态等字段。高并发
在操做时也能够有两种方式:ui
一是先重新手卡表中select出一条记录,而后去更新它的状态,再以后插入到领取记录表中。spa
但这种方式最大的问题在于高并发状况下,会出现多个用户select出了同一条记录,这样就只能有一我的成功,其余人会失败。设计
二是先重新手卡中更新一条记录,而后取出这条记录插入到领取记录表中。因为是先update再select因此很好适应高并发的状况,code
可是如今就遇到前面说的问题了:怎样获取刚才更新记录的ID呢?
下面代码是从stackoverflow上找到的答案,借用一下:
SET @update_id := 0;
UPDATE some_table SET row = 'value', id = (SELECT @update_id := id)
WHERE some_other_row = 'blah' LIMIT 1;
SELECT @update_id;
大体思路就是首先声明一个用户变量 @update_id ,以后在update数据时要多更新一个字段,就是将当前主键值更新为当前主键值(其实就是没更新),更新主键字段并非目的,只是为了将当前主键值赋值给@update_id,就是这句: ( SELECT @update_id := id )。 (我的理解,水平有限可能会有出入)
另外若是更新了多条记录也能够用下面的方式
SET @uids := null; UPDATE footable SET foo = 'bar' WHERE fooid > 5 AND ( SELECT @uids := CONCAT_WS(',', fooid, @uids) ); SELECT @uids;
注:上面的方法不适用于有HAVING、GROUP BY或者ORDER BY子句中,不然可能出入与预期不一样的结果。
参考官方手册说明 http://dev.mysql.com/doc/refman/5.1/zh/language-structure.html