insert...on duplicate key update语法详解
作者:ZhaoYingChao88 发布时间:2024-01-19 11:43:55
一.作用和使用场景
在mysql入库时,不能出现两条数据主键一致的情况,因为在两条数据的主键一致的情况下,mysql就会判定为待插入数据在数据库中存在重复数据,也就是说判断数据是否重复是根据主键来区别的。
但是有一些场景,如日志文件解析入库,消息队列接收数据入库等情况下可能解析到或者接收到待插入的重复数据存在重复数据则更新,不存在则插入。
这时如下语句的写法就派上用场了,on duplicate key update的作用也就是说存在重复数据则更新,不存在则插入。
二.例子详细讲解
场景大概是这样的,业务方的需求是查询一条语句在不在,如果在就给出一个update语句,更新这条记录,如果不在,就给出一个insert语句,插入这条记录。逻辑大概是:
result = select * from table;
if result = 0
insert the record into table;
else
update 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-26
2. 执行第二次:(与第一次的唯一(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-26
3 a 6 2019-06-25
6. 执行第六次:(无冲突插入,观察 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-26
3 a 6 2019-06-25
9 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操作会保留该条记录的原有值。
来源:https://blog.csdn.net/ZYC88888/article/details/104250372


猜你喜欢
- 本文实例讲述了Python编程修改MP3文件名称的方法。分享给大家供大家参考,具体如下:最近刚刚开始学习Python,顺便锻炼思维写的一个小
- 关于手机号码的提取,其实真正有用的部分就是re模块提供的正则表达式。使用正则表达式就能轻松地匹配到手机号码,由于功能比较简单这次并没有采用U
- 本文实例讲述了Python subprocess模块常见用法。分享给大家供大家参考,具体如下:subprocess模块是python从2.4
- 前言在pytorch中, 想删除tensor中的指定行列,原本以为有个函数或者直接把某一行赋值为[]就可以,结果发现没这么简单,因此用了一个
- 最常见的方式就是为字段设置主键或唯一索引,当插入重复数据时,抛出错误,程序终止,但这会给后续处理带来麻烦,因此需要对插入语句做特殊处理,尽量
- import osimport sysimport MySQLdbdef getStatus(conn):  
- 前言因近期进行时间序列分析时遇到了数据预处理中的缺失值处理问题,其中日期缺失和填充在网上没有找到较好较全资料,耗费了我一晚上工作时间,所以下
- Python3将数据保存为txt文件的方法,具体内容如下所示:f = open("data/model_Weight.txt&qu
- 一.思路我们通过网页版的微信公众平台的图文消息中的超链接获取到我们需要的接口从接口中我们可以得到对应的微信公众号和对应的所有微信公众号文章。
- 源代码:# coding=utf-8import loggingimport osimport timeLEVELS={'debug
- 本文实例讲述了python实现计算资源图标crc值的方法,分享给大家供大家参考。具体方法如下:实现该功能的关键在于解析资源信息,找到icon
- 如何制作一个分页程序?确实,翻页程序可以相互借鉴,但具体到每一需求,还是有较大差别的。代码入下,供参考:<%language=&quo
- PHP 备份 mysql 数据库的源代码,在完善的 PHP+Mysql 项目中,在后台都会有备份 Mysql 数据库的功能,有了这个功能,对
- 引言在review 一些代码中,发现经常某个类型定义的方法,其接收者既有值类型,又有指针类型,然后 Goland 就有提示: Struct
- 结合order by关键词和limit关键词是可以解决很多的topN问题,比如从二手房数据集中查询出某个地区的最贵的10套房,从电商交易数据
- 本文说明向外扩展数据库系统的两个选项,从而实现更高的可扩展性:水平数据划分和垂直数据划分当我提到向外扩展数据库系统时,我实际上只是讨论对数据
- 废话不多说,直接上代码:# coding:utf-8from urllib import requestfrom urllib import
- 背景(background)在项目中经常会使用。这篇文章主要讲解的是实际项目中的5个实例。通过具体的分析来达到学习的目的。1,Li列表通过u
- 图像文件是自己仿照mnist格式制作,每张图像大小为128*128import structimport matplotlib.pyplot
- 1. yum list installed | grep php 查看安装的php版本mod_php72w.x86_64 7.2.1-1.w