在我们的日常开发中,你是否遇到过这种情景:查看某条记录是否存在,不存在的话创建一条新记录,存在的话更新某些字段。你的处理方式是不是就是按照下面这样?

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

这样的写法可能有如下几点缺陷:

  • 少量的性能消耗。执行了两次sql,按照一条sql一去一回两次网络传输的话,那么这就是4次。 
    * 麻烦。一个很简单的逻辑缺要写十来行代码。
  • 在高并发下会出问题。比如当我们获取到了需要的数据,在更新之前,有另外一个请求恰好删除了该条记录,我们的更新操作就没起到作用;再或者,如果我们更新操作的写法有问题,比如更新列a,我们使用a = $row[a] + 1而不是a = a +1这种原子性的操作,有可能别的请求已经修改过了该字段,从而造成数据出错。

幸好,MySql考虑到了这点,提供了insert … on duplicate key update的语法,该语法在insert的时候,如果insert的数据会引起唯一索引(包括主键索引)的冲突,即这个唯一值重复了,则不会执行insert操作,而执行后面的update操作。

例如,现在有表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。

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时。

MySql之on duplicate key update详解的更多相关文章

  1. MySQL中ON DUPLICATE KEY UPDATE使用

    今天做推断插入用到了MySQL中ON DUPLICATE KEY UPDATE,如今Mark下面! 假设你想做到数据库中没有数据的话插入数据.有数据的话更新数据,那么你能够选择ON DUPLICATE ...

  2. MySQL于ON DUPLICATE KEY UPDATE采用

    今天我们做的推断插入用途MySQL于ON DUPLICATE KEY UPDATE.现在,Mark下面! 假设你想做的事,再有就是在数据库中插入数据没有数据.如果有数据更新数据,然后你可以选择ON D ...

  3. mysql优化 ON DUPLICATE KEY UPDATE

    场景:比如,有一张表,专门记录业务里的唯一数据记录,这张表里如果存在此唯一数据的记录就更新此行数据的某个字段,如果此唯一数据不存在,那么就添加一条最新数据. 一贯操作:如果不知道mysql有 ON D ...

  4. mysql INSERT ... ON DUPLICATE KEY UPDATE语句

    网上关于INSERT ... ON DUPLICATE KEY UPDATE大多数文章都是同一篇文章转来转去,首先这个语法的目的是为了解决重复性,当数据库中存在某个记录时,执行这条语句会更新它,而不存 ...

  5. mysql insert on duplicate key, update, ignore

    insert 语句中不能使用where,所以如果需要根据插入的数据在已有的数据库表是否重复做一些操作可以使用下面三种方法: 1. 使用insert,捕获duplicate错误 2. insert in ...

  6. mysql:on duplicate key update与replace into

    在往表里面插入数据的时候,经常需要:a.先判断数据是否存在于库里面:b.不存在则插入:c.存在则更新 一.replace into 前提:数据库里面必须有主键或唯一索引,不然replace into ...

  7. 【MySQL】ON DUPLICATE KEY UPDATE

    之前没用过这个操作,甚至没见过--最近接触到,而且还挺有用. 作用:若 KEY 不重复,则插入记录:否则更新记录. 单条操作: INSERT INTO table(a, b, c) VALUES (1 ...

  8. MySQL中insert ignore into, on duplicate key update,replace into,insert … select … where not exist的一些用法总结

    在MySQL中进行条件插入数据时,可能会用到以下语句,现小结一下.我们先建一个简单的表来作为测试: CREATE TABLE `books` ( `id` ) NOT NULL AUTO_INCREM ...

  9. mysql插入数据时 insert IGNORE、ON DUPLICATE KEY UPDATE、replace into

    转: mysql insert时几个操作DELAYED .IGNORE.ON DUPLICATE KEY UPDATE的区别 博客分类: mysql基础应用   mysql insert时几个操作DE ...

随机推荐

  1. Linux基础入门(新版)(实验九-实验十二)

    实验九 简单文本入门 一.常用的文本处理命令 二.文本处理命令 1.tr 命令 tr 命令可以用来删除一段文本信息中的某些文字.或者将其进行转换. 使用方式: tr [option]...SET1 [ ...

  2. 转:label标签的特殊用法

    容易被忽略的label标签 原始作用 label标签是HTML原生的标签,其原始的作用参考这里 label 标签为 input 元素定义标注(标记). label 元素不会向用户呈现任何特殊效果.不过 ...

  3. Nginx启动出错 error while loading shared libraries:

    在centos5.7 32位上编译安照 nginx-1.1.16 出错 [root@localhost conf]# /usr/local/nginx/sbin/nginx/usr/local/ngi ...

  4. jQuery对象与DOM对象之间的转换

    刚开始学习jQuery,可能一时会分不清楚哪些是jQuery对象,哪些是DOM对象.至于DOM对象不多解释,我们接触的太多了,下面重点介绍一下jQuery,以及两者相互间的转换. 什么是jQuery对 ...

  5. Think Python - Chapter 18 - Inheritance

    In this chapter I present classes to represent playing cards, decks of cards, and poker hands.If you ...

  6. SecureCRT最佳配色方法+直接修改默认配置方法 - imsoft.cnblogs

    SecureCRT默认显示效果是黑白且刺眼的主题,看起来很不舒服.经过一番搜索,总结结果如下,直接设置默认属性,设置一次,不需再改. 效果图: 具体操作方法: Options->Global O ...

  7. Matlab 2012a 下载和安装教程

    迅雷下载地址    http://bbs.pinggu.org/thread-1426998-1-1.html(下载速度比较快) 1 Setup.exe 2. 不使用 internet 安装 then ...

  8. jquery 下了框

    //选中特定值 $("#Select_GBType").attr("value", "选中项ID"); //获取选中项的值 $(" ...

  9. Spring MVC 属性文件读取注入到静态字段

    目录(?)[-] servlet-contextxml configproperties 示例属性 ConfigInfo 对应的配置bean 使用   在项目中,有些参数需要配置到属性文件xxx.pr ...

  10. spring二级缓存的ehcache 的 配置文件

    <ehcache> <!-- Sets the path to the directory where cache .data files are created. If the p ...