一.作用和使用场景

在mysql入库时,不能出现两条数据主键一致的情况,因为在两条数据的主键一致的情况下,mysql就会判定为待插入数据在数据库中存在重复数据,也就是说判断数据是否重复是根据主键来区别的

但是有一些场景,如日志文件解析入库,消息队列接收数据入库等情况下可能解析到或者接收到待插入的重复数据存在重复数据则更新不存在则插入

这时如下语句的写法就派上用场了,on duplicate key update的作用也就是说存在重复数据则更新不存在则插入。

二.例子详细讲解

场景大概是这样的,业务方的需求是查询一条语句在不在,如果在就给出一个update语句,更新这条记录,如果不在,就给出一个insert语句,插入这条记录。逻辑大概是:

result =  select * from table;
if result = 0insert the record into table;
elseupdate the record;

这样的操作乍一看没有什么问题,但是仔细分析分析,还是有些瓶颈的,目前来看,我能分析到的瓶颈有两个,

其一:

每次要执行2个SQL,效率比较差;

其二:

当我们在高并发的情况下跑这条语句,如果程序崩溃,不能保证操作的原子性。


**说明:
1. on duplicate key update 含义:1)如果在INSERT语句末尾指定了 on duplicate key update,并且插入行后会导致在一个UNIQUE索引或PRIMARY KEY中出现重复值,则在出现重复值的行执行UPDATE;2)如果不会导致唯一值列重复的问题,则插入新行。2. values(col_name)函数只是取当前插入语句中的插入值,并没有累加功能。如:count = values(count) 取前面 insert into 中的 count 值,并更新当有多条记录冲突,需要插入时,前面的更新值都被最后一条记录覆盖,所以呈现出取最后一条更新的现象。如:count = count + values(count) 依然取前面 insert into 中的 count 值,并与原记录值相加后更新回数据库,这样,当多条记录冲突需要插入时,就实现了不断累加更新的现象。注:insert into ... on duplicate key update ... values() 这个语句尽管在冲突时执行了更新,并没有插入,但是发现依然会占用 id 序号(自增),出现很多丢失的 id 值,可参看下面案例

函数使用说明:在一个 INSERT … ON DUPLICATE KEY UPDATE … 语句中,你可以在 UPDATE 子句中使用 VALUES(col_name ) 函数,用来访问来自该语句的 INSERT 部分的列值。换言之,UPDATE 子句中的 VALUES(col_name ) 访问需要被插入的 col_name 的值 , 并不会发生重复键冲突。这个函数在多行插入中特别有用。 VALUES() 函数只在 INSERT ... UPDATE 语句中有意义,而在其它情况下只会返回 NULL。

**案例:
0. 创建案例表 word_count_0626(单词计数表)use test;CREATE TABLE IF NOT EXISTS word_count_0626 (id int(11) NOT NULL AUTO_INCREMENT,word varchar(64) NOT NULL,count int(11) DEFAULT 0,date date NOT NULL,PRIMARY KEY (id),UNIQUE KEY word (word, date)  // (word,date) 两字段组合唯一) ENGINE=InnoDB DEFAULT CHARSET=utf8;注:curdate() 为 "2019-06-26"
1. 执行第一次:(首次数据库表中没有数据,正常插入)insert into word_count_0626 (word, count, date) values ('a',5,curdate()) on duplicate key update count=values(count);# 结果显示:id   word    count    date 1    a       5        2019-06-262. 执行第二次:(与第一次的唯一(word,date)冲突,执行更新)insert into word_count_0626 (word, count, date) values ('a',6,curdate()) on duplicate key update count=values(count);# 结果显示:id   word    count    date 1    a       6        2019-06-26  (更新)3. 执行第三次:insert into word_count_0626 (word, count, date) values ('a',6,curdate()-1),    // 取前一天,不会冲突('a',7,curdate()) // 冲突on duplicate key update count=values(count);# 结果显示:id   word    count    date 1    a       7        2019-06-26  (更新)3    a       6        2019-06-25  (新插入)4. 执行第四次:(更新冲突的最后一条插入值)insert into word_count_0626 (word, count, date) values ('a',2,curdate()),  // 冲突('a',1,curdate())  // 冲突on duplicate key update count=values(count);# 结果显示:id   word    count    date 1    a       1        2019-06-26  (更新最后一条插入值)3    a       6        2019-06-25  (不变)5. 执行第五次:(更新冲突的累加插入值)insert into word_count_0626 (word, count, date) values ('a',2,curdate()),('a',1,curdate()) on duplicate key update count=count+values(count); // 实现每行累加# 结果显示:id   word    count    date 1    a       4        2019-06-263    a       6        2019-06-256. 执行第六次:(无冲突插入,观察 id 键值,出现了很多丢失,id 直接跳到了 9)insert into word_count_0626 (word, count, date) values ('b',2,curdate())on duplicate key update count=count+values(count);# 结果显示:id   word    count    date 1    a       4        2019-06-263    a       6        2019-06-259    b       2        2019-06-26

说明:

insert...on duplicate key方法

简单写一个例子,内容大致如下:

1、首先创建一个包含id,name,age的表,其中id是主键;

2、在这个表中插入一条id=1的记录;

3、使用insert...on duplicate key update语法插入一条id=2的记录;

4、使用同样的语法更新id=1的记录;

mysql 23:12:32>>create table test_1( -> id int primary key auto_increment,-> name varchar(20),-> age int not null-> ) engine=innodb charset=utf8;
Query OK, 0 rows affected (0.08 sec)mysql 23:13:26>>insert into test_1 values (1,'yyz',16);
Query OK, 1 row affected (0.01 sec)mysql 23:13:58>>select * from test_1;
+----+------+-----+
| id | name | age |
+----+------+-----+
|  1 | yyz  |  16 |
+----+------+-----+
1 row in set (0.00 sec)mysql 23:14:36>>insert into test_1 (id,name,age) values (2,'yyz',18) on duplicate key update age=18;
Query OK, 1 row affected (0.01 sec)mysql 23:15:08>>select * from test_1;
+----+------+-----+
| id | name | age |
+----+------+-----+
|  1 | yyz  |  16 |
|  2 | yyz  |  18 |
+----+------+-----+
2 rows in set (0.00 sec)mysql 23:15:17>>insert into test_1 (id,name,age) values (1,'yyz',18) on duplicate key update age=18;
Query OK, 2 rows affected (0.00 sec)mysql 23:15:28>>select * from test_1;
+----+------+-----+
| id | name | age |
+----+------+-----+
|  1 | yyz  |  18 |
|  2 | yyz  |  18 |
+----+------+-----+
2 rows in set (0.00 sec)

insert...on duplicate key update语法的作用,可以分析到,当发生主键冲突的时候,可以直接进行update操作,这个update操作里面可以更新任意想要更新的列;而没有主键冲突的时候,相当于对这个表进行了一次插入操作。

Replace操作

Replace语句。使用Replace插入一条记录时,如果不重复,Replace就和Insert的功能一样,如果有重复记录,Replace就使用新记录的值来替换原来的记录值。

使用REPLACE的最大好处就是可以将Delete和Insert合二为一,形成一个原子操作。这样就可以不必考虑在同时使用Delete和Insert时添加事务等复杂操作了。

在使用Replace时,表中必须有唯一索引,而且这个索引所在的字段不能允许空值,否则Replace就和Insert完全一样的。

在执行Replace后,系统返回了所影响的行数,如果返回1,说明在表中并没有重复的记录,如果返回2,说明有一条重复记录,系统自动先调用了Delete删除这条记录,然后再记录用Insert来插入这条记录。

不同之处

有了上面的知识储备,这两条命令的不同之处就显而易见了,replace是删除记录,然后再重新insert,而insert...on duplicate key update是直接在该条记录上修改,所以二者的差别主要有以下两处:

1、当表中存在自增值的时候,如果表中存在某条记录,replace语法会导致自增值+1,而insert...on duplicate key update语法不会;

2、当表中的某些字段中包含默认值的时候,replace操作插入不完全字段的记录,会导致其他字段直接使用默认值,而insert...on duplicate key update操作会保留该条记录的原有值。

insert...on duplicate key update语法详解相关推荐

  1. mysql insert into on_MySQL之INSERT INTO ON DUPLICATE KEY UPDATE用法详解 | 夕辞

    MySQL数据库使用中如果主键或唯一键冲突,会报错,因此我们会用到insert into on duplicate key update语法,但是该语法具体怎么用以及返回什么值,今天就来讨论下. 首先 ...

  2. MySQL的INSERT ··· ON DUPLICATE KEY UPDATE使用的几种情况

    MySQL的INSERT ··· ON DUPLICATE KEY UPDATE使用的几种情况 在MySQL数据库中,如果在insert语句后面带上ON DUPLICATE KEY UPDATE 子句 ...

  3. “ INSERT IGNORE”与“ INSERT…ON DUPLICATE KEY UPDATE”

    在执行包含多行的INSERT语句时,我想跳过重复的条目,否则它们会导致失败. 经过研究后,我的选择似乎是使用以下任一方法: ON DUPLICATE KEY UPDATE ,这意味着要付出一定的代价进 ...

  4. 深入mysql ON DUPLICATE KEY UPDATE 语法的分析

    mysql "ON DUPLICATE KEY UPDATE" 语法 如果在INSERT语句末尾指定了ON DUPLICATE KEY UPDATE,并且插入行后会导致在一个UNI ...

  5. MySQL中 ON DUPLICATE KEY UPDATE语法的使用

    MySQL ON DUPLICATE KEY UPDATE 为Mysql特有语法 ON DUPLICATE KEY UPDATE 用法与说明 Mysql中INSERT ... ON DUPLICATE ...

  6. insert ... on duplicate key update产生death lock死锁原理

    转载自  insert ... on duplicate key update产生death lock死锁原理 前言 编辑 我们在实际业务场景中,经常会有一个这样的需求,插入某条记录,如果已经存在了则 ...

  7. mysql批量insert bug_MySQL Bug insert into on duplicate key update 语法更新 text blob 大字段导致 MySQL crash...

    1. 背景 业务执行 SQL 导致 MySQL 进程 Crash,做故障切换后,新的主库又 Crash 了.查看 MySQL 错误日志,发现多次 Crash 时的堆栈相同,如下: Thread poi ...

  8. (转载)[MySQL技巧]INSERT INTO… ON DUPLICATE KEY UPDATE

    (转载)http://blog.zol.com.cn/2299/article_2298921.html MySQL 自4.1版以后开始支持INSERT - ON DUPLICATE KEY UPDA ...

  9. MySQL的INSERT INTO··· ON DUPLICATE KEY UPDATE使用的几种情况

    保存或更新 在MySQL数据库中,如果在insert语句后面带上ON DUPLICATE KEY UPDATE 子句,而要插入的行与表中现有记录的惟一索引或主键中产生重复值,那么就会发生旧行的更新:如 ...

最新文章

  1. SSRS:使用SQL2008教程学习Reporting Services之数据库AdventureWorks2008问题_学习笔记1
  2. 【python】numpy数组的维度增减方法
  3. 【干货】2021顾客体验十二大趋势:从“千人一面”到“千人千面”.pdf(附下载链接)...
  4. SpringMVC json/xml自动转换
  5. 从小白到中级高级软件测试工程师成长路线!--(上篇)
  6. 1、数据结构的基本逻辑结构、存储结构和运算
  7. VB6程序实现XP或者WIN7风格
  8. python程序中1—10的乘积_[求助]1个数1到10的乘积
  9. 威信游戏小程序源码-合成大西瓜小游戏(合成版)源码 附带流量主功能
  10. phpstudy的基本使用方法
  11. Python_动态二维码的制作
  12. Windows系统百宝箱
  13. php unpack 详解,【PHP】 pack unpack 详解
  14. Power BI----各类切片器的使用
  15. codeforces 834-A. The Useless Toy
  16. java无法读取方案文档_解决Spring的java项目打包后执行出现“无法读取方案文档...“、“原因为 1) 无法找到文档; 2) 无法读取文档; 3) 文档的根元素不是...”问题...
  17. ubuntu下使用github安装R Packages[已解决]
  18. 商标图形也会侵权?商标侵权如何界定?
  19. 浙里办前端H5对接小结(复盘自用)
  20. matlab-结构体struct

热门文章

  1. 如何解决笔记本电脑不接电源自动断网的问题?
  2. 温控驱动(五)dts参数解析、节点作用
  3. vdat文件怎么转成mp4文件
  4. Access-Control-Allow-Origin: Dealing with CORS Errors in Angular
  5. 真正的程序员就应该这样.
  6. 生存分析绘图——Kaplan-Meier生存曲线
  7. 微信订阅号和服务器,微信订阅号与服务号有什么不同?
  8. 中链云 | IPFS入门知识(五)
  9. 【C++学习笔记】标准库类型string
  10. 碧蓝航线服务器维护到几点,碧蓝航线7月9号维护停服多长时间?科研第三期介绍[多图]...