mysql replace语句
语法
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
REPLACE [LOW_PRIORITY | DELAYED] [INTO] tbl_name [PARTITION (partition_name,...)] [(col_name,...)] {VALUES | VALUE} ({expr | DEFAULT},...),(...),...Or:REPLACE [LOW_PRIORITY | DELAYED] [INTO] tbl_name [PARTITION (partition_name,...)] SET col_name={expr | DEFAULT}, ...Or:REPLACE [LOW_PRIORITY | DELAYED] [INTO] tbl_name [PARTITION (partition_name,...)] [(col_name,...)] SELECT ... |
原理
replace的工作机制有点像insert,只不过如果在表里如果一行有PRIMARY KEY或者UNIQUE索引,那么就会把老行删除然后插入新行。如:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
root@test 03:23:55>show create table lingluo\G*************************** 1. row *************************** Table: lingluoCreate Table: CREATE TABLE `lingluo` ( `a` int(11) NOT NULL DEFAULT '0', `b` int(11) DEFAULT NULL, `c` int(11) DEFAULT NULL, `d` int(11) DEFAULT NULL, PRIMARY KEY (`a`),--------------------------同时存在PK约束 UNIQUE KEY `uk_bc` (`b`,`c`)----------------唯一索引约束) ENGINE=InnoDB DEFAULT CHARSET=gbk1 row in set (0.01 sec)root@test 02:01:44>select * from lingluo;Empty set (0.00 sec)root@test 03:27:40>replace into lingluo values(1,10000,3,4);--------表里没有已存在的记录相当于insertQuery OK, 1 row affected (0.00 sec)-----------------------affect_rows是1binlog格式: |

|
1
2
3
|
root@test 02:11:18>replace into lingluo values(1,10000,3,5);-------已经存在记录,且PK和UK同时冲突的时候,相当于先delete再insertQuery OK, 2 rows affected (0.00 sec)----------------------affect_rows是2,是delete和insert行数的总和binlog格式: |

|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
root@test 02:26:09>select * from lingluo;+---+-------+------+------+| a | b | c | d |+---+-------+------+------+| 1 | 10000 | 3 | 5 |+---+-------+------+------+1 row in set (0.00 sec)root@test 02:31:54>replace into lingluo values(1,10000,4,5);-------已经存在记录,且PK同时冲突的时候,相当于先delete再insertQuery OK, 2 rows affected (0.00 sec)---------------------------------affect_rows是2,是delete和insert行数的总和root@test 02:32:02>select * from lingluo;+---+-------+------+------+| a | b | c | d |+---+-------+------+------+| 1 | 10000 | 4 | 5 |+---+-------+------+------+binlog格式: |

|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
root@test 02:37:04>replace into lingluo values(4,10000,6,5);Query OK, 1 row affected (0.00 sec)root@test 02:37:59>replace into lingluo values(6,10000,6,5);-------已经存在记录,且UK同时冲突的时候,直接updateQuery OK, 2 rows affected (0.00 sec)---------------------------------affect_rows是2root@test 02:40:31>select * from lingluo;+---+-------+------+------+| a | b | c | d |+---+-------+------+------+| 1 | 10000 | 4 | 5 || 3 | 10000 | 5 | 5 || 6 | 10000 | 6 | 5 |+---+-------+------+------+3 rows in set (0.00 sec)binlog格式: |

疑问:
既然uk冲突的时候是update,那么为什么affect_rows都是2呢?让我们从源码上分析看下:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
|
指定列replace:root@test 03:34:37>select * from u;+----+------+------+| id | age | d |+----+------+------+| 0 | 1 | 126 || 1 | 0 | 1 || 3 | 1 | 123 || 4 | 1 | 127 || 5 | 0 | 12 || 7 | 2 | 129 |+----+------+------+6 rows in set (0.00 sec)root@test 03:34:37>select * from u;+----+------+------+| id | age | d |+----+------+------+| 0 | 1 | 126 || 1 | 0 | 1 || 3 | 1 | 123 || 4 | 1 | 127 || 5 | 0 | 12 || 7 | 2 | 129 |+----+------+------+6 rows in set (0.00 sec)root@test 03:34:40>replace into u (age,d)values(0,130);Query OK, 2 rows affected, 1 warning (0.01 sec)root@test 03:40:39>show warnings;+---------+------+-----------------------------------------+| Level | Code | Message |+---------+------+-----------------------------------------+| Warning | 1364 | Field 'id' doesn't have a default value |+---------+------+-----------------------------------------+1 row in set (0.00 sec)root@test 03:40:47>select * from u;+----+------+------+| id | age | d |+----+------+------+| 0 | 0 | 130 |-----------------因为id是parimary但是没有auto_creasement,由126变成130| 1 | 0 | 1 || 3 | 1 | 123 || 4 | 1 | 127 || 5 | 0 | 12 || 7 | 2 | 129 |+----+------+------+6 rows in set (0.00 sec) |
用的时候需要注意的是:
如果指定replace列的话,尽量写全,要不然没有输入值的列数据会被赋成默认值(因为是先delete在insert),就和普通的insert是一样的,所以如果你要执行replace语句的话是需要insert和delete权限的。
如果你需要执行
SET,就相当于执行col_name=col_name+ 1.col_name= DEFAULT(col_name) + 1replace语句如果不深入看的话,就和insert一样,执行完后没什么反应
例:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
|
root@test 04:20:04>select * from u;+----+------+------+| id | age | d |+----+------+------+| 0 | 0 | 130 || 1 | 0 | 1 || 3 | 1 | 123 || 4 | 1 | 127 || 5 | 0 | 12 || 7 | 2 | 129 |+----+------+------+6 rows in set (0.00 sec)root@test 04:20:10>replace into u (id,d) values(8,232);Query OK, 1 row affected (0.01 sec)root@test 04:20:39>select * from u;+----+------+------+| id | age | d |+----+------+------+| 0 | 0 | 130 || 1 | 0 | 1 || 3 | 1 | 123 || 4 | 1 | 127 || 5 | 0 | 12 || 7 | 2 | 129 || 8 | NULL | 232 |+----+------+------+7 rows in set (0.00 sec)root@test 04:20:43>replace into u (id,d) values(7,232);Query OK, 3 rows affected (0.01 sec)----------注意这里affect_rows是3,因为主键7已经存在,唯一索引232已经存在,所以需要删除id为7和8的行,然后插入新行root@test 04:20:52>select * from u;+----+------+------+| id | age | d |+----+------+------+| 0 | 0 | 130 || 1 | 0 | 1 || 3 | 1 | 123 || 4 | 1 | 127 || 5 | 0 | 12 || 7 | NULL | 232 |+----+------+------+6 rows in set (0.00 sec)root@test 04:20:55> |
MySQL给replace和load data....replace用的算法是:
尝试向表里插入新行
当表里唯一索引或者primary key冲突的时候:
a. delete冲突行
b.往表里再次插入新行
如果遇到重复行冲突,存储过程很可能当作update执行,而不是delete+insert,但是显式上都是一样的。这里没有用户可见的影响除了存储引擎层Handler_xxx的状态变量。
因为REPLACE ... SELECT语句的结果依赖于select的行的顺序,但是顺序没办法保证都是一样的,有可能从master和slave的都不一样。正是基于这个原因,MySQL 5.6.4以后,REPLACE ... SELECT语句被标记为基于statement的复制模式不安全的。基于这个变化,当使用STATEMENT记录二进制日志的时候,如果有这样的语句就会在log里面输出一个告警,同样当使用MIXED行复制模式也会记录告警。
在MySQL5.6.6之前的版本,replace影响分区表就像MyISAM使用表级锁锁住所有的分区表一样。当使用 REPLACE ... PARTITION语句时确实会发生上述情况。(使用基于行锁的InnoDB引起不会发生这种情况。)在MySQL 5.6.6以后的版本MySQL使用分区锁,只有当分区(只要没有分区表的列更新)包含了REPLACE语句并且WHERE实际匹配到的才会锁住那个分区;否则的话就会锁住整个表。
操作形式:

binlog格式:

结论
当存在pk冲突的时候是先delete再insert
当存在uk冲突的时候是直接update
mysql replace语句的更多相关文章
- Mysql Replace语句的使用
Mysql Replace语句的语法: REPLACE [LOW_PRIORITY | DELAYED] [INTO] tbl_name [(col_name,...)] VALUES ({expr ...
- 慎用MySQL replace语句
语法: REPLACE [LOW_PRIORITY | DELAYED] [INTO] tbl_name [PARTITION (partition_name,...)] [(col_name,... ...
- MySQL数据库INSERT、UPDATE、DELETE以及REPLACE语句的用法详解
本篇文章是对MySQL数据库INSERT.UPDATE.DELETE以及REPLACE语句的用法进行了详细的分析介绍,需要的朋友参考下 MySQL数据库insert和update语句引:用于操作数 ...
- MySQL replace函数替换字符串语句的用法(mysql字符串替换)
MySQL replace函数我们经常用到,下面就为您详细介绍MySQL replace函数的用法,希望对您学习MySQL replace函数方面能有所启迪. 最近在研究CMS,在数据转换的时候需要用 ...
- MySQL中的replace语句
一.背景 当使用replace语句更新access_apps表时,原有的mark列.remark列的信息丢失. CREATE TABLE `access_apps` ( `base` varcha ...
- 转载:MySQL数据库INSERT、UPDATE、DELETE以及REPLACE语句的用法详解
转自:http://www.jb51.net/article/39199.htm 本篇文章是对MySQL数据库INSERT.UPDATE.DELETE以及REPLACE语句的用法进行了详细的分析介绍, ...
- MySQL 当记录不存在时insert,当记录存在时update(ON DUPLICATE KEY UPDATE, REPLACE语句)
MySQL 当记录不存在时insert,当记录存在时更新 网上基本有三种解决方法. 第一种:示例一:insert多条记录 假设有一个主键为 client_id 的 clients 表,可以使用下面的语 ...
- MySQL replace into 使用详解 及 注意事项
REPLACE的运行与INSERT很相似.只有一点例外,假如表中的一个旧记录与一个用于PRIMARY KEY或一个UNIQUE索引的新记录具有相同的值,则在新记录被插入之前,旧记录被删除.注意:除非表 ...
- MySQL replace into 说明(insert into 增强版)
MySQL replace into 说明(insert into 增强版) 在插入数据到一个表时,通常是这种情况:1. 先推断数据是否存在: 2. 假设不存在,则插入:3.假设存在,则更新. 在 S ...
随机推荐
- NavigationViewController页面间通信及传值
使用进行页面跳转时,应该使用方法来跳转至下一页面,这样的话,下一页面同样在容器中. 1AloneSetPrizeViewController *setPrize = [[AloneSetPrizeVi ...
- 显式等待-----Selenium快速入门(十)
上一篇说了元素定位过程中的隐式等待,今天我们来探讨一下显示等待.显式等待,其实就是在使用WebDriverWait这个对象,进行等待.显式等待对比隐式等待,多了一些人性化的设置,可以说是更细化的隐式等 ...
- 数据导出之winform导出word(三)
本篇文章补充讲解上篇文章中word模板的制作. ① 新建一个word文档 ② 定位到要插入书签的位置 ③ 菜单栏 “插入” -> “书签”,输入书签名,点击“添加” 可以多处位置使用同样的书签名 ...
- ueditor图片上传插件的使用
在项目里使用到ueditor图片上传插件,以前图片上传都是直接使用js代码直接上传图片,比较麻烦,而且效率也比较低,而ueditor这款插件完美的解决了这个问题,这个是百度开发的一款富文本编辑器,在这 ...
- CodeForces 540C Ice Cave (BFS)
http://codeforces.com/problemset/problem/540/C Ice Cave Time Limit:2000MS Memory Limit:262 ...
- DDoS防护之TCP防护
本文由 网易云 发布. TCP协议,相信对于每一个开发工程师都不陌生.由于该协议是一个面向连接,可靠的特性,广泛应用于现在互联网的应用中.如常见的Web.SSH.FTP等都是基于TCP协议.目前TC ...
- Flask系列03--Flask的路由 app.route中的参数, 动态参数路由
Flask–路由 添加路由的两种方式 第一种 @app.route("/my_de") def detail() 第二种(了解即可) app.add_url_rule(" ...
- Python任意网段Web端口信息探测工具
此篇关于多线程工具的文章,非常适合新手学习,工具效率也挺高的,代码也比较完善,如题. 本文作者:i春秋签约作家——Aedoo 0×00 前言 笔者前一段时间发布了原创文章,“[Python黑客] Py ...
- D09——C语言基础学PYTHON
C语言基础学习PYTHON——基础学习D09 20180903内容纲要: 线程.进程 1.paramiko 2.线程.进程初识 3.多线程 (1)线程的调用方式 (2)join (3)线程锁.递归锁. ...
- 【xsy1214】 异或路径(xorpath) 点分治+可持久化trie
题目大意:给你一棵$n$个点的树,每个点有一个点权$x$,问你所有路径中点权异或和最大的路径的异或和 数据范围:$n≤30000$,$x≤2^{31}-1$. 如果是边上有点权的话非常简单,直接一个$ ...