replace into的存在的几种情况

  • 当表存在主键并且存在唯一键的时候

    • 如果只是主键冲突
mysql> select * from auto;
+----+---+------+---------+
| id | k | v | extra |
+----+---+------+---------+
| 2 | 2 | 2 | extra 2 |
| 3 | 3 | 3 | extra 3 |
| 4 | 1 | 1-1 | NULL |
+----+---+------+---------+
3 rows in set (0.00 sec) mysql>
mysql> show create table auto\G
*************************** 1. row ***************************
Table: auto
Create Table: CREATE TABLE `auto` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`k` int(10) unsigned NOT NULL,
`v` varchar(100) DEFAULT NULL,
`extra` varchar(200) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `uk_k` (`k`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=latin1
1 row in set (0.00 sec)

这里我们插入一条主键已经存在的4的数据

mysql> replace into auto(id,k)values(4,5);
Query OK, 2 rows affected (0.01 sec) mysql> select * from auto;
+----+---+------+---------+
| id | k | v | extra |
+----+---+------+---------+
| 2 | 2 | 2 | extra 2 |
| 3 | 3 | 3 | extra 3 |
| 4 | 5 | NULL | NULL |
+----+---+------+---------+
3 rows in set (0.00 sec) mysql> show create table auto \G
*************************** 1. row ***************************
Table: auto
Create Table: CREATE TABLE `auto` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`k` int(10) unsigned NOT NULL,
`v` varchar(100) DEFAULT NULL,
`extra` varchar(200) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `uk_k` (`k`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=latin1
1 row in set (0.00 sec)

发现,auto_increment并没有+1,而是针对原来的那一条id=4的记录进行了update,因为没有指定其他列(v,extra)的值,所以,update的时候都使用了默认值.

  • 如果主键跟唯一键都冲突并且在同一行里
mysql> select * from auto;
+----+---+------+---------+
| id | k | v | extra |
+----+---+------+---------+
| 2 | 2 | 2 | extra 2 |
| 3 | 3 | 3 | extra 3 |
| 4 | 5 | NULL | NULL |
| 5 | 6 | 6 | NULL |
+----+---+------+---------+
4 rows in set (0.00 sec) mysql> show create table auto \G
*************************** 1. row ***************************
Table: auto
Create Table: CREATE TABLE `auto` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`k` int(10) unsigned NOT NULL,
`v` varchar(100) DEFAULT NULL,
`extra` varchar(200) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `uk_k` (`k`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=latin1
1 row in set (0.00 sec) mysql>
mysql>
mysql> replace into auto(id,k,extra)values(5,6,77);
Query OK, 2 rows affected (0.01 sec) mysql> select * from auto;
+----+---+------+---------+
| id | k | v | extra |
+----+---+------+---------+
| 2 | 2 | 2 | extra 2 |
| 3 | 3 | 3 | extra 3 |
| 4 | 5 | NULL | NULL |
| 5 | 6 | NULL | 77 |
+----+---+------+---------+
4 rows in set (0.00 sec) mysql> show create table auto \G
*************************** 1. row ***************************
Table: auto
Create Table: CREATE TABLE `auto` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`k` int(10) unsigned NOT NULL,
`v` varchar(100) DEFAULT NULL,
`extra` varchar(200) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `uk_k` (`k`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=latin1
1 row in set (0.00 sec)

我们发现,auto_increment也并没有+1,而是针对原来的那一条id=6的记录进行了update,因为没有指定其他列(v)的值,所以,update的时候都v使用了默认值变成了null

  • 如果主键跟唯一键都冲突不在同一行,对应2条记录呢

我们来看下:

mysql> show create table auto \G
*************************** 1. row ***************************
Table: auto
Create Table: CREATE TABLE `auto` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`k` int(10) unsigned NOT NULL,
`v` varchar(100) DEFAULT NULL,
`extra` varchar(200) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `uk_k` (`k`)
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=latin1
1 row in set (0.00 sec) mysql> select * from auto;
+----+---+------+---------+
| id | k | v | extra |
+----+---+------+---------+
| 2 | 2 | 2 | extra 2 |
| 3 | 3 | 3 | extra 3 |
| 4 | 5 | NULL | NULL |
| 6 | 6 | 66 | NULL |
+----+---+------+---------+
4 rows in set (0.00 sec) mysql> replace into auto(id,k,v)values(6,2,88);
Query OK, 3 rows affected (0.03 sec)

像上面的,主键id=6对应一条记录,唯一索引k=2对应id=2的另外一条记录,所以我们当前插入的记录就会跟2行数据有冲突,我们replace into 看看会有什么结果

mysql> replace into auto(id,k,v)values(6,2,88);
Query OK, 3 rows affected (0.03 sec) mysql> select * from auto;
+----+---+------+---------+
| id | k | v | extra |
+----+---+------+---------+
| 3 | 3 | 3 | extra 3 |
| 4 | 5 | NULL | NULL |
| 6 | 2 | 88 | NULL |
+----+---+------+---------+
3 rows in set (0.00 sec) mysql> show create table auto \G
*************************** 1. row ***************************
Table: auto
Create Table: CREATE TABLE `auto` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`k` int(10) unsigned NOT NULL,
`v` varchar(100) DEFAULT NULL,
`extra` varchar(200) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `uk_k` (`k`)
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=latin1
1 row in set (0.00 sec)

我们发现auto_increment并没有+1,MySQL把原来的id=6的这条记录上进行uppdate,但是发现唯一索引k出现了冲突,所以就把对应冲突的那条数据删除,再进行更新,由于没有指定更新字段extra的数据,所以就把extra更新为默认数据

  • 如果仅仅是唯一键冲突呢?
mysql> select * from auto;
+----+---+------+---------+
| id | k | v | extra |
+----+---+------+---------+
| 2 | 2 | 2 | extra 2 |
| 3 | 3 | 3 | extra 3 |
| 4 | 5 | NULL | NULL |
| 5 | 6 | NULL | 77 |
+----+---+------+---------+
4 rows in set (0.00 sec) mysql> show create table auto \G
*************************** 1. row ***************************
Table: auto
Create Table: CREATE TABLE `auto` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`k` int(10) unsigned NOT NULL,
`v` varchar(100) DEFAULT NULL,
`extra` varchar(200) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `uk_k` (`k`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=latin1
1 row in set (0.00 sec) mysql>
mysql> replace into auto(k,v)values(6,66);
Query OK, 2 rows affected (0.04 sec) mysql> select * from auto;
+----+---+------+---------+
| id | k | v | extra |
+----+---+------+---------+
| 2 | 2 | 2 | extra 2 |
| 3 | 3 | 3 | extra 3 |
| 4 | 5 | NULL | NULL |
| 6 | 6 | 66 | NULL |
+----+---+------+---------+
4 rows in set (0.00 sec) mysql> show create table auto \G
*************************** 1. row ***************************
Table: auto
Create Table: CREATE TABLE `auto` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`k` int(10) unsigned NOT NULL,
`v` varchar(100) DEFAULT NULL,
`extra` varchar(200) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `uk_k` (`k`)
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=latin1
1 row in set (0.00 sec)

这时候,我们发现,,auto_increment已经+1了。MySQL这时候的执行步骤是,首先往表里面插入一条数据,这时候auto_increment+1,但是在插入的时候发现唯一索引的k冲突了,然后把冲突的这条数据删除,然后重新插入,对于没有指定其他列(extra)的值,如extra都使用了默认值变成了null

现在我们可以下结论了:

  1. 当replace into 记录只与主键冲突的时候,auto_increment不会增加,它会对与主键冲突的那一条记录进行更新,没有指定的列将会被更新为默认值
  2. 当replace into 记录与主键跟唯一索引同时冲突的时候,auto_increment不会增加
    1. 如果冲突的主键和索引在同一行记录,则replace into只做更新,对于没有指定值的其他列,将会被更新为默认值,
    2. 如果冲突的主键和索引分别对应2行数据,则MySQL将会删除唯一索引的那一行记录,更新对应主键的那一行记录。
  3. 当replace into 记录只与唯一索引进行冲突的时候,auto_increment + 1,再对数据进行更新。
  • 最后我们可以对总结分析下,MySQL对replace into的操作是首先是insert操作,如果insert失败,则对insert失败的这条记录进行update,如果update还是失败,则会进行delete操作之后再update。
  • 具体流程是这样的:insert记录,发现主键冲突,则update这一行,update的时候发现存在唯一键冲突,则delete对应的唯一键的行后再进行update。如果insert成功,auto_increment自然+1了,然后对这条记录进行update,update的时候发现存在唯一键冲突,则delete对应的唯一键的行后再进行update。

mysql replace into 的使用情况的更多相关文章

  1. MySQL replace into 说明(insert into 增强版)

    MySQL replace into 说明(insert into 增强版) 在插入数据到一个表时,通常是这种情况:1. 先推断数据是否存在: 2. 假设不存在,则插入:3.假设存在,则更新. 在 S ...

  2. Mysql replace into

    mysqlsql serverinsert 在向表中插入数据的时候,经常遇到这样的情况:1. 首先判断数据是否存在: 2. 如果不存在,则插入:3.如果存在,则更新. 在 SQL Server 中可以 ...

  3. MySQL "replace into" 的坑以及insert相关操作

    下面我们主要说一下在插入时候的几种情况: 1:insert ignore 2:replace into 3:ON DUPLICATE KEY UPDATE 关于insert ignore: 关于rep ...

  4. MySQL replace into 用法

    讨人喜欢的 MySQL replace into 用法(insert into 的增强版) 在向表中插入数据的时候,经常遇到这样的情况:1. 首先判断数据是否存在: 2. 如果不存在,则插入:3.如果 ...

  5. MySQL replace into 用法(insert into 的增强版)

    转 http://blog.csdn.net/risingsun001/article/details/38977797 MySQL replace into 用法(insert into 的增强版) ...

  6. MySQL replace into 使用详解 及 注意事项

    REPLACE的运行与INSERT很相似.只有一点例外,假如表中的一个旧记录与一个用于PRIMARY KEY或一个UNIQUE索引的新记录具有相同的值,则在新记录被插入之前,旧记录被删除.注意:除非表 ...

  7. MySQL replace函数替换字符串语句的用法(mysql字符串替换)

    MySQL replace函数我们经常用到,下面就为您详细介绍MySQL replace函数的用法,希望对您学习MySQL replace函数方面能有所启迪. 最近在研究CMS,在数据转换的时候需要用 ...

  8. MySQL "replace into" 的坑

    MySQL 对 SQL 有很多扩展,有些用起来很方便,但有一些被误用之后会有性能问题,还会有一些意料之外的副作用,比如 REPLACE INTO. 比如有这样一张表: CREATE TABLE `au ...

  9. mysql如何查看索引使用情况以及优化 - guols0612

    mysql中支持hash和btree索引.innodb和myisam只支持btree索引,而memory和heap存储引擎可以支持hash和btree索引 我们可以通过下面语句查询当前索引使用情况: ...

随机推荐

  1. Java集合:整体结构

    一.Java中集合 Java中集合类是Java编程中使用最频繁.最方便的类.集合类作为容器类可以存储任何类型的数据,当然也可以结合泛型存储指定的类型(不过泛型仅仅在编译期有效,运行时是会被擦除的).集 ...

  2. linux:终端常用命令 + vi命令修改文件及保存 方法

    首先介绍一下Ubuntu下各个目录的一般作用: /  这就是根目录,一台电脑有且只有一个根目录,所有的文件都是从这里开始的.举个例子:当你在终端里输入“/home”,你其实是在告诉电脑,先从/(根目录 ...

  3. SpringBoot(11) SpringBoot自定义拦截器

    自定义拦截器共两步:第一:注册.第二:定义拦截器. 一.注册 @Configuration 继承WebMvcConfigurationAdapter(SpringBoot2.X之前旧版本) 旧版本代码 ...

  4. Perl正则表达式引用

    正则表达式两篇: 基础正则 Perl正则 本文是对Perl正则的一点扩展,主要内容是使用qr//创建正则对象,以及一些其它的技巧. qr//创建正则对象 因为可以在正则模式中使用变量替换,所以我们可以 ...

  5. Go基础系列:nil channel用法示例

    Go channel系列: channel入门 为select设置超时时间 nil channel用法示例 双层channel用法示例 指定goroutine的执行顺序 当未为channel分配内存时 ...

  6. oracle10G/11G官方迅雷下载地址合集

    原文链接:https://blog.csdn.net/zlsunnan/article/details/8058235 ORACLE11GR2 Oracle Database 11g Release ...

  7. word2vec初探

    在自然语言处理入门里我们提到了词向量的概念,tf-idf的概念,并且在实际的影评正负面预测项目中使用了tf-idf,取得了还算不错的效果.这一篇,我们来尝试一下使用来自google的大名鼎鼎的word ...

  8. C#基础知识总结(五)

    摘要 其他的数据类型:常量.枚举(enum).结构(struct).数组一.常量 语法:const 类型 变量名 = 变量值 常量称之为值不可变的变量! 在定义的地方赋值,其他的地方不能赋值. 常量变 ...

  9. Redis常用命令与配置

    常用命令 测试客户端与服务器是否正常连接:ping   ( 补:返回pong表示成功 ) 正则获取键:keys pattern 判断一个键是否存在:exists key 删除一个键:del key 获 ...

  10. Xhprof graphviz Warning: proc_open() [function.proc-open]: CreateProcess failed, error code 解决方法

    Xhprof在windows下点击[View Full Callgraph]调用graphviz软件时.警告Warning: proc_open() [function.proc-open]: Cre ...