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 : lingluo Create 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=gbk 1 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); --------表里没有已存在的记录相当于insert Query OK, 1 row affected (0.00 sec) -----------------------affect_rows是1 binlog格式: |
1
2
3
|
root@test 02:11:18> replace into lingluo values (1,10000,3,5); -------已经存在记录,且PK和UK同时冲突的时候,相当于先delete再insert Query 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再insert Query 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同时冲突的时候,直接update Query OK, 2 rows affected (0.00 sec) ---------------------------------affect_rows是2 root@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 ...
随机推荐
- .NET 简易方法拦截器
伟大的无产阶级Willaim曾说过:"无论你觉得自己多么的了不起,也永远有人比你更强".对,我说过!我就是william. 今天想记录一下在项目中遇到的一个比较有意思的东西,异常拦 ...
- Win(Phone)10开发第(3)弹,简单的Demo程序网络请求json解析列表显示
先分享一个由Json字符串直接生成解析对应的类的工具: jsonclassgenerator14 百度天气接口 下面是由一个小功能(又特么的是天气)的实现,记录下下UAP的流程和结构(其实跟之前一模一 ...
- ASP.NET MVC 实现带论坛功能的网站 第一步——-实现用户注册.
首先我们要实现用户的注册功能.进入visual studio 点击文件->新建->项目->选择ASP.NET Web应用程序(.NET Framework)->选择的模板为MV ...
- Python常用第三方模块(长期更新)
1.keyboard #监控键盘 2.PIL#处理图片 3.operator #操作列表 4.shelve #数据存储方案 保存dat文件 5.optparse #处理命令行参数 6.configpa ...
- C# 后缀名
用Visual Studio进行开发时项目内会有很多文件,其中常见的文件名后缀及其功能如下: .sln:解决方案文件,为解决方案资源管理器提供显示管理文件的图形接口所需的信息. .csproj:项目文 ...
- 可方便扩展的JIRA Rest Web API的封装调用
JIRA是一个缺陷跟踪管理系统,被广泛应用于缺陷跟踪.客户服务.需求收集.流程审批.任务跟踪.项目跟踪和敏捷管理等工作领域,当我们需要把第三方业务系统集成进来时,可以调用他的API. JIRA本身的A ...
- pymysql模块使用
一.写函数的原因 写这个函数的原因就是为了能够不每次在用Python用数据库的时候还要在写一遍 做个通用函数做保留,也给大家做个小小的分享,函数不是最好的,希望有更好的代码的朋友能提出 互相学习 二 ...
- Spring Security构建Rest服务-0701-个性化用户认证流程
上一篇说了用户认证的基本流程,但是上一篇当访问一个受保护的服务后,如果未认证会调到默认的登录页面,这样是不行的,而且认证成功后,就直接访问了那个服务,如果想要做认证成功后做一些操作,还需要自定义. 个 ...
- MySQL的Sleep进程占用大量连接解决方法
第一部分为产生大量sleep进程的原理及对应解决方法第二部分为设置wait_timeout值,有效减少sleep进程 ========================================= ...
- 使用Apache Bench对网站性能进行测试
使用Apache Bench对网站性能进行测试