MySQL中的replace语句
一、背景
当使用replace语句更新access_apps表时,原有的mark列、remark列的信息丢失。
CREATE TABLE `access_apps` ( `base` varchar (11) NOT NULL DEFAULT '' , `business` varchar (64) NOT NULL DEFAULT '' , `owt` varchar (64) NOT NULL DEFAULT '' , `pdl` varchar (64) NOT NULL DEFAULT '' , `app_group_id` varchar (64) NOT NULL DEFAULT '' , `app_artifact_id` varchar (64) NOT NULL DEFAULT '' , `app` varchar (128) NOT NULL DEFAULT '' , `appkey` varchar (128) NOT NULL DEFAULT '' , `version` varchar (128) NOT NULL DEFAULT '' , `status` tinyint(1) NOT NULL DEFAULT '0' , `mark` int (11) NOT NULL DEFAULT '0' , `remark` varchar (128) NOT NULL DEFAULT '' , `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP , PRIMARY KEY (`base`,`business`,`owt`,`pdl`,`app_group_id`,`app_artifact_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; |
@Insert ( "replace into access_apps(base,business,owt,pdl,app_group_id,app_artifact_id,app,appkey,version,status) " + "values(#{base},#{business},#{owt},#{pdl},#{app_group_id},#{app_artifact_id},#{app},#{appkey},#{version},#{status})" ) void saveAccessRecord(AccessRecord accessRecord); |
access_apps表中有mark、remark列,replace语句中没有mark、remark列。
错误原因:
错误认为replace语句相当于当主键冲突时,已修改的列将使用新值,未修改的列将使用旧值
replace语句对于缺失的列将使用默认值,而不是当前行中的值,导致原有的列信息丢失。
二、replace语句详解
MySQL中replace语句具体算法如下:
1. 尝试把新行插入到表中
2. 当因为主键(PRIMARY KEY)冲突错误或(UNIQUE INDEX)唯一索引重复错误而造成插入失败时:
a. 从表中删除含有重复关键字值的冲突行
b. 再次尝试把新行插入到表中
可以看出replace语句相当于insert操作或者delete+insert操作,因此,为了能够使用replace语句,必须同时具备insert和delete的权限。
replace语句执行时,分以下两种情况:
情况1:insert
当不存在主键冲突或唯一索引冲突,相当于insert操作
情况2:delete and insert
当存在主键冲突或唯一索引冲突,相当于delete操作,加insert操作
所有列的值均取自在replace语句中被指定的值,所有缺失的列的值被设置为列的默认值,这和INSERT一样。
不能引用当前行的值,然后用于更新新行。(因为当当前行与新行发生冲突时,当前行将被删除,也就无法被引用了!)
例如,如果使用一个形如“SET col_name = col_name + 1”的赋值,则对位于右侧的列名称的引用会被作为DEFAULT(col_name)处理。
因此,该赋值相当于SET col_name = DEFAULT(col_name) + 1。
replace语句的返回值
replace语句会返回一个数,来指示受影响的行的数目。该数是被删除和被插入的行数的和。
1.如果对于一个replace语句,返回值为1,则一行被插入,同时没有行被删除。
2.如果该数大于1,则在新行被插入前,有一个或多个旧行被删除。如果表包含多个唯一索引,并且新行与不同行的不同的唯一索引发生了重复。
示例1:test表id作为主键
CREATE TABLE test ( id INT UNSIGNED NOT NULL AUTO_INCREMENT, data VARCHAR (64) DEFAULT NULL , ts TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP , PRIMARY KEY (id) ); |
mysql> REPLACE INTO test VALUES (1, 'Old' , '2014-08-20 18:47:00' ); Query OK, 1 row affected (0.04 sec) mysql> REPLACE INTO test VALUES (1, 'New' , '2014-08-20 18:47:42' ); Query OK, 2 rows affected (0.04 sec) mysql> SELECT * FROM test; + ----+------+---------------------+ | id | data | ts | + ----+------+---------------------+ | 1 | New | 2014-08-20 18:47:42 | + ----+------+---------------------+ 1 row in set (0.00 sec) |
第一个replace语句执行时,test表中没有数据,没有发生冲突,所以相当于执行了insert操作,返回值为1(1 row affected)。
第二个replace语句执行时,id=1的数据已存在,发生了主键冲突,所以相当于先执行了delete操作,然后执行了insert操作,返回值为2(2 rows affected)。
示例2:test表id,ts作为主键
CREATE TABLE test2 ( id INT UNSIGNED NOT NULL AUTO_INCREMENT, data VARCHAR (64) DEFAULT NULL , ts TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP , PRIMARY KEY (id, ts) ); |
mysql> REPLACE INTO test2 VALUES (1, 'Old' , '2014-08-20 18:47:00' ); Query OK, 1 row affected (0.05 sec) mysql> REPLACE INTO test2 VALUES (1, 'New' , '2014-08-20 18:47:42' ); Query OK, 1 row affected (0.06 sec) mysql> SELECT * FROM test2; + ----+------+---------------------+ | id | data | ts | + ----+------+---------------------+ | 1 | Old | 2014-08-20 18:47:00 | | 1 | New | 2014-08-20 18:47:42 | + ----+------+---------------------+ 2 rows in set (0.00 sec) |
因id,ts作为主键,replace时未发生主键冲突,所以均相当于insert操作。
三、参考资料
https://dev.mysql.com/doc/refman/5.7/en/replace.html MySQL官网replace语法
http://www.cnblogs.com/c-961900940/p/6197878.html MySQL中replace into的用法
http://www.cnblogs.com/martin1009/archive/2012/10/08/2714858.html mysql replace into用法详细说明
MySQL中的replace语句的更多相关文章
- mysql中常用的语句整理
mysql中常用的语句: 1:创建带自增长的主键的表 DROP TABLE IF EXISTS user_login ; CREATE TABLE user_login ( user_id INT ...
- Mysql中的条件语句if、case
Mysql中的条件语句在我们对数据进行转换的时候比较有用,这样就不需要创建中转表. IF 函数 IF(expr1,expr2,expr3) 如果 expr1 是TRUE (expr1 <> ...
- MySQL中执行sql语句错误 Error Code: 1093. You can't specify target table 'car' for update in FROM clause
MySQL中执行sql语句错误 Error Code: 1093. You can't specify target table 'car' for update in FROM clause 201 ...
- 浅谈MySQL中优化sql语句查询常用的30种方法 - 转载
浅谈MySQL中优化sql语句查询常用的30种方法 1.对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引. 2.应尽量避免在 where 子句中使 ...
- 重新认识MySQL中的COUNT语句
在数据库的增删改查操作中,使用最频繁的就是查询操作. 而在所有查询操作中,统计数量操作更是经常被用到. 关于数据库中行数统计,无论是MySQL还是Oracle亦或者是SqlServer,都有一个函数可 ...
- MySQL中使用replace into语句批量更新表数据
作为示例,我们在这里使用名为testdb的数据库,并且在其中创建两张一模一样的表: drop table if exists test_table_1; create table test_table ...
- 在MySQL中阻止UPDATE语句没有添加WHERE条件的发生
如果在生产环境中使用UPDATE语句更新表数据,此时如果忘记携带本应该添加的WHERE条件,那么..Oh,no…后果可能不堪设想.那么有没有什么办法可以阻止这样的事情发生,又不使用任何的审核工具呢.. ...
- mysql中,执行delete语句时出现Lock wait timeout exceeded问题
问题描述: 当我插入一条记录时,在调用save方法的时候出现了异常(记录重复了),导致了后面的commit语句不能执行了.这时我在数据库中删除重复记录时发现该表已经被锁上了.即出现错误.但过了一会再次 ...
- 关于mysql中实现replace的sql语句
update 表名 set 字段名=replace(字段名, '旧字符串', '新字符串')
随机推荐
- Android逆向分析(2) APK的打包与安装背后的故事
前言 上一次我们反编译了手Q,并遇到了Apktool反编译直接crash的问题,虽然笔者很想在这次解决这个问题,但在解决途中,发现该保护依赖于很多知识,所以本次先插入一下,正所谓知其然知其所以然,授之 ...
- 【Django】 gunicorn部署纪要
使用Gunicorn 来部署Django应用, 没有一步一步写怎么操作,简单记录下重要的点,方面以后查阅. 主要的方式还是Nginx反向代理到Gunicorn, Gunicorn wsgi来启动Dja ...
- 属性动画基础之ValueAnimator
概述 属性动画是谷歌在android3.0(API level 11)时候给我们带来了属性动画,真正意义上带来了"动画",以前的帧动画也就4中效果的组合(旋转.淡入淡出.放大缩小. ...
- 闫燕飞:Kafka的高性能揭秘及优化
欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 本文首发在云+社区,未经许可,不得转载. 大家下午好,我是来自腾讯云基础架构部ckafka团队的高级工程师闫燕飞.今天在这里首先为大家先分享 ...
- webpack.config.js配置文件
1.基本配置 webpack在执行时,除在命令行传入参数,还可以通过指定的配置文件来执行.默认会搜索当前目录下webpack.config.js.这个文件是一个node.js模块,返回一个json格式 ...
- Visual Studio Community 2013,功能完整,免费使用
http://www.infoq.com/cn/news/2014/11/VSC2013 微软刚刚宣布了.NET平台的开源计划,与此同时,它还推出了源自Visual Studio Profession ...
- 使用AngularJS开发中的几个问题
1.AngularJS的模板绑定机制好像和其$http服务也有一定关系,如果用jQuery Ajax的返回值赋给$scope的作用域变量,整个绑定显示的节奏慢一个事件,神器果然麻烦啊. 2.对hidd ...
- ThinkPHP5零基础搭建CMS系统(一)
了解学习thinkphp5应该是2016年年底的事情,当时还没有接触过thinkphp3版本,觉得通过手册直接上手学习tp5蛮轻松的,现在从零记录下,搭建可扩展的CMS. 1.ThinkPHP环境搭建 ...
- logistic 回归
logistic回归 1.算法思想 根据给定的数据集确定分类的边界.这个分类的边界就是我们所要求的回归函数. 所谓的回归其实就是最佳拟合,回归函数就是确定最佳回归参数,然后对不同的特征赋予不同的权重 ...
- 使用nginx缓存服务器上的静态文件
一.nginx缓存的优点 如图所示,nginx缓存,可以在一定程度上,减少源服务器的处理请求压力. 因为静态文件(比如css,js, 图片)中,很多都是不经常更新的.nginx使用proxy_cach ...