MySql之INSERT INTO…ON DUPLICATE KEY UPDATE详解

news/2024/6/15 10:38:10 标签: mysql, 数据库, on duplicate key update, insert update

在我们的日常开发中,经常会遇到过这样的情景:查看某条记录是否存在,不存在的话创建一条新记录,存在的话更新某些字段。
你会采用怎么样的处理方式呢?

$result = mysql_query('select * from xxx where id = 1');
$row = mysql_fetch_assoc($result);
if($row){
    mysql_query('update ...');
}else{
    mysql_query('insert ...');
}

其实,MySql已经考虑到了这点,提供了insert into … on duplicate key update的语法,该语法在insert的时候,如果insert的数据会引起唯一索引(包括主键索引)的冲突,即这个唯一值重复了,则不会执行insert操作,而执行后面的update操作。
注意:ON DUPLICATE KEY UPDATE只是MySQL的特有语法,并不是SQL标准语法!
例如,现在有表test,test表中有字段a,在a上有主键或者唯一索引,并且表中只有一条a=1, b=1的数据,现在执行如下的sql:
insert into test (a,b) values (1,2) on duplicate key update b = b + 1;
因为a=1的记录已存在了,所以不会执行insert,而会在该条记录上执行update语言b=b+1,记录会变成a=1,b=2
insert into test (a,b) values (2,2) on duplicate key update b = b + 1;
因为a=2的记录不存在,所以执行insert
如果行作为新记录被插入,则受影响的行为1;如果原有记录被更新,则受影响行为2;如果原有记录已存在,但是更新的值和原有值相同,则受影响行为0。

多唯一索引冲突的情况说明:
为了测试方便,我们建了下面的数据表:

create table test(
a int not null primary key,
b int not null UNIQUE key,
c int not null
)

输入数据:insert into test values(1,1,1), (2,2,2);
然后执行:insert into test values(1,2,3) on duplicate key update c = c + 1;
因为a和b都是唯一索引,插入的数据在两条记录上产生了冲突,然而执行后只有第一条记录被修改:

mysql> select * from test;
+---+---+---+
| a | b | c |
+---+---+---+
| 1 | 1 | 2 |
| 2 | 2 | 2 |
+---+---+---+
2 rows in set (0.00 sec)

上面的语句等同于:update test set c=c+1 where a=1 or b = 2 limit 1;
如果a=1 or b =2匹配多条记录,只有第一条记录被更新。所以,一般情况下,我们应该避免在有多个唯一索引的表中使用on duplicate key update

使用values()方法,在update中可以使用values()方法引用在insert中的值,如:
insert into test values(1,3,5) on duplicate key update c = values( c )+ 1;
该语句会使a=1的记录中c字段的值更新为6,因为values(c)的值是引用的insert部分的值,在这个例子中就是insert into test values(1,3,5) 中的5,所以最终更新的值为6。
注意:VALUES()函数只在INSERT…UPDATE语句中有意义,其它时候会返回NULL。

last_insert_id()
如果表含有auto_increment字段,使用insert … on duplicate key update插入或更新后,last_insert_id()返回auto_increment字段的值。

并发控制
在使用例如MyISAM这样的表级锁的分区表上使用insert … on duplicate key update时,会锁住所有分区表,而在例如使用InnoDB这样的行级锁的分区表上则不会锁住所有分区表。

delayed选项
delayed选项会被忽略,当我们使用on duplicate key update时。


http://www.niftyadmin.cn/n/1756911.html

相关文章

Oracle与MySQl对比

并发性 并发性是oltp数据库最重要的特性,但并发涉及到资源的获取、共享与锁定。 mysql:以表级锁为主,对资源锁定的粒度很大,如果一个session对一个表加锁时间过长,会让其他session无法更新此表中的数据。 虽然InnoD…

Redis 应用场景及应用实例

Redis是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。从2010年3月15日起,Redis的开发工作由VMware主持。 MySQLMemcached架构的问题 实际mysql是适合进行海量数据存储的,…

使用消息队列的 10 个理由

解耦 在项目启动之初来预测将来项目会碰到什么需求,是极其困难的。消息队列在处理过程中间插入了一个隐含的、基于数据的接口层,两边的处理过程都要实现这一接口。这允许你独立的扩展或修改两边的处理过程,只要确保它们遵守同样的接口约束。…

阿里RocketMQ如何解决消息的顺序和重复两大硬伤

分布式消息系统作为实现分布式系统可扩展、可伸缩性的关键组件,需要具有高吞吐量、高可用等特点。而谈到消息系统的设计,就回避不了两个问题: 消息的顺序问题消息的重复问题 RocketMQ作为阿里开源的一款高性能、高吞吐量的消息中间件&#…

杂谈 GC

在Hotspot VM实现中,主要有两大类GC Partial GC:并不会堆整个GC堆进行收集 young gc:只收集 young gen 的GCold gc:只收集 old gen 的GC,只有CMS的 concurrent collectionmixed GC:收集整个 young gen 以…

为什么要设计JAVA异常

从业这么多年,每当谈起异常,都是懵懵懂懂,只是依稀记得它是处理错误的,当程序出错,日志里会有异常日志,可以查看异常定位错误。但是最近突然发现一个问题,那就是处理错误不一定非的要用异常啊&a…

SLF4J处理日志

SLF4J是什么 The Simple Logging Facade for Java,笼统的讲就是slf4j是一系列的日志接口。 The Simple Logging Facade for Java (SLF4J) serves as a simple facade or abstraction for various logging frameworks, such as java.util.logging, logback and log4…

Maven依赖中的Scope、传递与隔断

Scope的分类 compile 默认的scope,表示 dependency 都可以在生命周期中使用。而且,这些dependencies 会传递到依赖的项目中。适用于所有阶段,会随着项目一起发布。即依赖的项目会参与到当前项目的编译、运行、测试以及打包发布,…