问题的起因,假设有一张表,里面保存了交易订单,每张订单有唯一的ID,有最后更新时间,还有数据,详情如下:

1
2
3
4
5
6
7
+-------+----------+------+-----+---------------------+-------+
| Field | Type     | Null Key Default             | Extra |
+-------+----------+------+-----+---------------------+-------+
| UID   | int(11)  | NO   | PRI | 0                   |       |
Time  | datetime | NO   |     | 0000-00-00 00:00:00 |       |
| Data  | int(11)  | YES  |     | NULL                |       |
+-------+----------+------+-----+---------------------+-------+

针对这张表会做追加及更新的操作,具体来说就是如果订单不存在就INSERT一条新的,如果已存在就UPDATE。由于入库前无法得知相应记录是否已存在,通常的做法无法以下几种:

1、先SELECT一下,再决定INSERT还是UPDATE;

2、直接UPDATE,如果受影响行数是0,再INSERT;

3、直接INSERT,如果发生主键冲突,再UPDATE;

这几种方法都有缺陷,对MySQL来说其实最好的是直接利用INSERT...ON DUPLICATE KEY UPDATE...语句,具体到上面的test表,执行语句如下 :

1
INSERT INTO test VALUES (1, '2016-1-1', 10) ON DUPLICATE KEY UPDATE Time='2016-1-1',Data=10;

可以很好的插入或更新数据,一条语句就搞定,至此一直工作得很好。

后来因为查询方式变更,要求将UID和Time两个字段做联合主键,此时表结构如下:

1
2
3
4
5
6
7
+-------+----------+------+-----+---------------------+-------+
| Field | Type     | Null Key Default             | Extra |
+-------+----------+------+-----+---------------------+-------+
| UID   | int(11)  | NO   | PRI | 0                   |       |
Time  | datetime | NO   | PRI | 0000-00-00 00:00:00 |       |
| Data  | int(11)  | YES  |     | NULL                |       |
+-------+----------+------+-----+---------------------+-------+

但是问题来了:一但Time字段被更新,即使是相同的UID,也被数据库认为是不同的主键,因此不会产生主键冲突,上面的语句就失效了,数据库里出现了很多UID相同的数据。

开始寻找解决办法,其实也简单,按MySQL文档里的说明,ON DUPLICATE KEY UPDATE语句判断是否冲突是依靠主键或唯一索引,因此为UID建立唯一索引就可以了。先建索引:

1
CREATE UNIQUE INDEX IDX_UID ON test(UID);

再测试一下插入:

1
2
INSERT INTO test VALUES (1, '2016-1-1', 10) ON DUPLICATE KEY UPDATE Time='2016-1-1',Data=10;
INSERT INTO test VALUES (1, '2016-2-1', 20) ON DUPLICATE KEY UPDATE Time='2016-2-1',Data=20;

MySQL复合主键下ON DUPLICATE KEY UPDATE语句失效问题的更多相关文章

  1. Mysql中Insert into xxx on duplicate key update问题

    要点:Insert into xxx on duplicate key update可以在唯一索引重复的情况下,进行更新操作.           (1) 插入里边的字段应该只有一个 唯一索引:   ...

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

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

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

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

  4. mysql 插入重复值 INSERT ... ON DUPLICATE KEY UPDATE

    向数据库插入记录时,有时会有这种需求,当符合某种条件的数据存在时,去修改它,不存在时,则新增,也就是saveOrUpdate操作.这种控制可以放在业务层,也可以放在数据库层,大多数数据库都支持这种需求 ...

  5. MySQL 当记录不存在时insert,当记录存在时update(ON DUPLICATE KEY UPDATE, REPLACE语句)

    MySQL 当记录不存在时insert,当记录存在时更新 网上基本有三种解决方法. 第一种:示例一:insert多条记录 假设有一个主键为 client_id 的 clients 表,可以使用下面的语 ...

  6. mysql 添加数据如果数据存在就更新ON DUPLICATE KEY UPDATE和REPLACE INTO

    #下面建立game表,设置name值为唯一索引. CREATE TABLE `game` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar( ...

  7. 步步为营Hibernate全攻略(四)剪不断理还乱之:复合主键 && 组合映射

    一:复合主键 复合主键即两个或多个字段联合起来作为主键,它的通常做法是将主键相关字段抽取出来放到一个单独的类中,但是这样的类是有要求的: 1.      必须实现序列化接口 2.      必须覆盖e ...

  8. mysql 中 replace into 与 insert into on duplicate key update 的使用和不同点

    replace into和insert into on duplicate key update都是为了解决我们平时的一个问题 就是如果数据库中存在了该条记录,就更新记录中的数据,没有,则添加记录. ...

  9. INSERT ... ON DUPLICATE KEY UPDATE Syntax

    一 mybatis中返回自动生成的id 当有时我们插入一条数据时,由于id很可能是自动生成的,如果我们想要返回这条刚插入的id怎么办呢.在mysql数据中我们可以在insert下添加一个selectK ...

随机推荐

  1. spring源码学习(一):eclipse导入spring源码

    前言 对于一门技术,我们最先是了解它(what),然后再熟练的使用它(how)以及何时用它(when),最后肯定要看透它(why).spring作为Java开发人员可以说是最熟悉不过的了,基本每个Ja ...

  2. Altium中Logo的导入方法及大小调整

    Altium中Logo的导入方法及大小调整   LOGO识别性是企业标志的重要功能之一,特点鲜明.容易辨认,很多客户需要在PCB设计阶段导入LOGO标示归属特性.如果LOGO是CAD图纸,可以直接按照 ...

  3. QTP日常积累

    1.init同步测试对象 同步测试对象: CODE: Browser("百度一下,你就知道").Page("百度一下,你就知道").WebEdit(" ...

  4. [学习笔记]SiftGPU入门

    当有读者看到我这篇SiftGPU入门的学习笔记时,相信你已经读过了高博那篇<SLAM拾萃:SiftGPU>,那篇文章写于16年,已经过去两年的时间.在我尝试配置SiftGPU的环境时,遇到 ...

  5. Linux AD 身份统一验证(SSO)

    http://www.toxingwang.com/linux-unix/linux-admin/584.html Linux+samba-winbind+AD实现统一认证 2013年04月27日 ⁄ ...

  6. Linux文件句柄数调整

    首先介绍下Linux系统中"一切都是文件". 1. Linux系统文件句柄数概念 文件句柄(Windows) 文件描述符(Unix/Linux):file discriptor,f ...

  7. docker 从本地拷贝文件

    1.找到docker的ID全称 docker inspect -f '{{.Id}}' docker_name 2.执行拷贝命令 docker cp 本地文件路径 ID全称:docker路径 3.如果 ...

  8. FFT(快速傅里叶变换)算法详解

    多项式的点值表示(Point Value Representation) 设多项式的系数表示(Coefficient Representation): \[ \begin{align*} \mathr ...

  9. 持续更新 | 想不到的key

    前言 开坑写一些我认为比较巧妙的东西想不到的东西 正文 判断回文串的时候 考虑一下枚举中心位往两边扩展 最大子矩阵与单调栈 遇难则反系列 算合法可以转换成算不合法.同理,不合法转换成合法计算有时也会简 ...

  10. ubuntu16.04 CUDA, CUDNN 安装

    这次介绍的是使用 tensorflow1.8, cuda9.0, cudnn7.0的版本 https://developer.nvidia.com/cuda-90-download-archive 下 ...