【原创】MySQL 返回更新值(RETURNING)

本文涉及的产品
云数据库 RDS MySQL Serverless,0.5-2RCU 50GB
简介:

在写SQL中,经常会有诸如更新了一行记录,之后要获取更新过的这一行。 本身从程序来说,没啥难度,大不了把这行缓存起来,完了直接访问。 但是从数据库的角度出发,怎么能快速的拿出来,而又不对原表进行二次扫描? 比如其他数据库提供了如下的语法来实现:


返回更新掉的行:

1
2
3
4
5
6
7
8
9
t_girl=#  update  t1  set  log_time = now()  where  id  in  (1,2,3) returning *;
  id |          log_time          
----+----------------------------
   1 | 2014-11-26 11:06:53.555217
   2 | 2014-11-26 11:06:53.555217
   3 | 2014-11-26 11:06:53.555217
(3  rows )
UPDATE  3
Time : 6.991 ms


返回删除掉的行:

1
2
3
4
5
6
7
t_girl=#  delete  from  t1  where  id < 2 returning *;
  id |          log_time          
----+----------------------------
   1 | 2014-11-26 11:06:53.555217
(1 row)
DELETE  1
Time : 6.042 ms


返回插入后的行:

1
2
3
4
5
6
7
8
t_girl=#  insert  into  t1  select  1,now() returning *;
  id |          log_time          
----+----------------------------
   1 | 2014-11-26 11:07:40.431766
(1 row)
INSERT  0 1
Time : 6.107 ms
t_girl=#



那在MySQL里如何实现呢? 

我可以创建几张内存表来来保存这些返回值,如下:

1
2
3
4
5
6
CREATE  TABLE  t1_insert ENGINE MEMORY  SELECT  FROM   t1  WHERE  FALSE ;
CREATE  TABLE  t1_update ENGINE MEMORY  SELECT  FROM   t1  WHERE  FALSE ;
CREATE  TABLE  t1_delete ENGINE MEMORY  SELECT  FROM   t1  WHERE  FALSE ;
ALTER  TABLE  t1_insert  ADD  PRIMARY  KEY  (id);
ALTER  TABLE  t1_update  ADD  PRIMARY  KEY  (id);
ALTER  TABLE  t1_delete  ADD  PRIMARY  KEY  (id);


以上建立了三张表来存放对应的操作。 t1_insert 保存插入;t1_update 保存更新;t1_delete 保存删除。


那这样的话,我来创建对应的触发器完成。


1
2
3
4
5
6
7
8
9
10
11
DELIMITER $$
USE `t_girl`$$
DROP  TRIGGER  /*!50032 IF EXISTS */ `tr_t1_insert_after`$$
CREATE
     /*!50017 DEFINER =  'root' @ 'localhost'  */
     TRIGGER  `tr_t1_insert_after`  AFTER  INSERT  ON  `t1` 
     FOR  EACH ROW  BEGIN
       REPLACE  INTO  t1_insert  VALUES  (new.id,new.log_time);
     END ;
$$
DELIMITER ;


1
2
3
4
5
6
7
8
9
10
11
DELIMITER $$
USE `t_girl`$$
DROP  TRIGGER  /*!50032 IF EXISTS */ `tr_t1_update_after`$$
CREATE
     /*!50017 DEFINER =  'root' @ 'localhost'  */
     TRIGGER  `tr_t1_update_after`  AFTER  UPDATE  ON  `t1` 
     FOR  EACH ROW  BEGIN
       REPLACE  INTO  t1_update  VALUES  (new.id,new.log_time);
     END ;
$$
DELIMITER ;


1
2
3
4
5
6
7
8
9
10
11
DELIMITER $$
USE `t_girl`$$
DROP  TRIGGER  /*!50032 IF EXISTS */ `tr_t1_delete_after`$$
CREATE
     /*!50017 DEFINER =  'root' @ 'localhost'  */
     TRIGGER  `tr_t1_delete_after`  AFTER  DELETE  ON  `t1` 
     FOR  EACH ROW  BEGIN
       REPLACE  INTO  t1_delete  VALUES  (old.id,old.log_time);;
     END ;
$$
DELIMITER ;


创建好了以上的表和触发器后, 拿到返回值就非常容易了, 我直接从以上几张表来查询就是。


我现在来演示:

更新:

1
2
3
4
5
mysql>  truncate  table  t1_update;
Query OK, 0  rows  affected (0.00 sec)
mysql>  UPDATE  t1  SET  log_time = NOW()  WHERE  id < 15;
Query OK, 3  rows  affected (0.01 sec)
Rows  matched: 3  Changed: 3  Warnings: 0

获取更新记录:

1
2
3
4
5
6
7
8
9
mysql>  select  from  t1_update;
+ ----+----------------------------+
| id | log_time                   |
+ ----+----------------------------+
| 12 | 2014-11-26 13:38:06.000000 |
| 13 | 2014-11-26 13:38:06.000000 |
| 14 | 2014-11-26 13:38:06.000000 |
+ ----+----------------------------+
rows  in  set  (0.00 sec)


插入:

1
2
3
4
mysql>  truncate  table  t1_insert;
Query OK, 0  rows  affected (0.00 sec)
mysql>  INSERT  INTO  t1  VALUES  (1,NOW());
Query OK, 1 row affected (0.08 sec)

获取插入记录:

1
2
3
4
5
6
7
mysql>  select  from  t1_insert;
+ ----+----------------------------+
| id | log_time                   |
+ ----+----------------------------+
|  1 | 2014-11-26 13:38:06.000000 |
+ ----+----------------------------+
1 row  in  set  (0.00 sec)


删除:

1
2
3
4
mysql>  truncate  table  t1_delete;
Query OK, 0  rows  affected (0.00 sec)
mysql>  DELETE  FROM  t1  WHERE  id < 15;
Query OK, 4  rows  affected (0.01 sec)

获取删除记录:

1
2
3
4
5
6
7
8
9
10
mysql>  select  from  t1_delete;
+ ----+----------------------------+
| id | log_time                   |
+ ----+----------------------------+
|  1 | 2014-11-26 13:38:06.000000 |
| 12 | 2014-11-26 13:38:06.000000 |
| 13 | 2014-11-26 13:38:06.000000 |
| 14 | 2014-11-26 13:38:06.000000 |
+ ----+----------------------------+
rows  in  set  (0.00 sec)





本文转自 david_yeung 51CTO博客,原文链接:http://blog.51cto.com/yueliangdao0608/1584932 ,如需转载请自行联系原作者
相关实践学习
基于CentOS快速搭建LAMP环境
本教程介绍如何搭建LAMP环境,其中LAMP分别代表Linux、Apache、MySQL和PHP。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
关系型数据库 MySQL Java
MySQL 巨坑:update 更新慎用影响行数做判断!!!
MySQL 巨坑:update 更新慎用影响行数做判断!!!
753 0
MySQL 巨坑:update 更新慎用影响行数做判断!!!
|
SQL 关系型数据库 MySQL
mysql中case when返回多个字段处理方案
一般情况下case when结构,返回的字段只能支持一个,但是会有很多业务场景中需要返回一个以上字段信息.这种问题有两个处理方案,一个是将case when结构进行改造,支持返回多个字段;另一种就是保持case when返回字段个数不变(只返回一个字段),修改业务逻辑,在service中按照case when返回一个字段进行处理.本文主要介绍第一种处理方案.下面结合一个业务场景说明如何进行处理.
|
SQL 关系型数据库 MySQL
mysql实战:左表数据全部展示,关联表有关联数据返回1,没有关联数据返回0
现在有一消息通知功能,后台发布的每条通知消息都会展示到APP端消息列表中,每条消息支持是否已读操作,从消息列表中点击进入详情视为完成已读操作;现在需要在查询出的用户消息列表信息,其中所有的通知消息信息要标注出是否已读.
mysql实战:左表数据全部展示,关联表有关联数据返回1,没有关联数据返回0
|
SQL 关系型数据库 MySQL
MySql 使用 NOT IN 返回值包含null值,返回数据不全
MySql 使用 NOT IN 返回值包含null值,返回数据不全
211 0
MySql 使用 NOT IN 返回值包含null值,返回数据不全
|
关系型数据库 MySQL
MySQL基础-删除/更新行为
添加了外键之后,再删除父表数据时产生的约束行为,我们就称为删除/更新行为。具体的删除/更新行为有以下几种:
155 0
|
关系型数据库 MySQL 索引
mysql更新varchar类型字段长度报错:ERROR 1074 (42000): Column length too big for column ‘value‘ (max = 21845);
mysql更新varchar类型字段长度报错:ERROR 1074 (42000): Column length too big for column ‘value‘ (max = 21845);
|
关系型数据库 MySQL
MySQL练习4——查询结果限制返回行数
MySQL练习4——查询结果限制返回行数!
|
关系型数据库 MySQL 测试技术
面试官:MySQL 中 update 更新,数据与原数据相同时会执行吗?大部分人答不上来!
面试官:MySQL 中 update 更新,数据与原数据相同时会执行吗?大部分人答不上来!
158 0
|
SQL 关系型数据库 MySQL
软件测试mysql面试题:编写SQL SELECT查询,该查询从Employee_Details表返回名字和姓氏。
软件测试mysql面试题:编写SQL SELECT查询,该查询从Employee_Details表返回名字和姓氏。
81 0
|
SQL 关系型数据库 MySQL
MySQL UPDATE 更新
MySQL UPDATE 更新
97 0