MySql中4种批量更新的方法

article/2025/10/21 9:05:08

https://yq.aliyun.com/ziliao/59813

MySql中4种批量更新的方法

   最近在完成MySql项目集成的情况下,需要增加批量更新的功能,根据网上的资料整理了一下,很好用,都测试过,可以直接使用。

   mysql 批量更新共有以下四种办法

1、.replace into 批量更新

   replace into test_tbl (id,dr) values (1,'2'),(2,'3'),...(x,'y');
   例子:replace into book (`Id`,`Author`,`CreatedTime`,`UpdatedTime`) values (1,'张飞','2016-12-12 12:20','2016-12-12 12:20'),(2,'关羽','2016-12-12 12:20','2016-12-12 12:20');

2、insert into ...on duplicate key update批量更新

https://dev.mysql.com/doc/refman/5.7/en/insert-on-duplicate.html

使用INSERT的时候 有表T(id,A,B,C,D)

插入的时候希望通过A,B索引唯一记录 ,有重复的时候更新C,D

INSERT INTO T(A,B,C,D) VALUES (a,b,c,d) ON DUPLICATE KEY UPDATE C=C+1,D=d 

这条语句相当于:

INSERT INTO ... VALUES ...

当INSERT(因为主键或唯一键冲突)失败时,执行

UPDATE ... SET ... WHERE A = a AND B = b

只是这个过程用一个原子语句来实现罢了,具体可参阅MySQL的官方文档: https://dev.mysql.com/doc/ref...

如果表中有多个唯一键,情况就更复杂了,有兴趣可以深入研究。
还有一个类似的语句叫 REPLACE 跟INSERT ... ON DUPLICATE KEY UPDATE作用类似,但原理是不一样的,有兴趣可参阅: https://dev.mysql.com/doc/ref...


  insert into test_tbl (id,dr) values (1,'2'),(2,'3'),...(x,'y') on duplicate key update dr=values(dr);

  例子:insert into book (`Id`,`Author`,`CreatedTime`,`UpdatedTime`) values (1,'张飞2','2017-12-12 12:20','2017-12-12 12:20'),(2,'关羽2','2017-12-12 12:20','2017-12-12 12:20') on duplicate key update Author=values(Author),CreatedTime=values(CreatedTime),UpdatedTime=values(UpdatedTime);

insert into tran_test (f1,f2) values ("A3",2),("B3",3) on duplicate key update f2=values(f2);

解释:f1是主键,唯一性,如果没有测插入(insert into tran_test (f1,f2) values ("A3",2),("B3",3))。有责更新,更新的内容为update f2=values(f2); values就是insert的关键字values(对应的更新字段)

insert into tran_test (f1,f2) values ("A3",2),("B3",3) on duplicate key update f2=10; 有责更新 f2=10

   replace into  和 insert into on duplicate key update的不同在于:

    replace into 操作本质是对重复的记录先delete 后insert,如果更新的字段不全会将缺失的字段置为缺省值,用这个要悠着点否则不小心清空大量数据可不是闹着玩的。
    insert into 则是只update重复记录,不会改变其它字段。

3.创建临时表,先更新临时表,然后从临时表中update

    create temporary table tmp(id int(4) primary key,dr varchar(50));
    insert into tmp values  (0,'gone'), (1,'xx'),...(m,'yy');
    update test_tbl, tmp set test_tbl.dr=tmp.dr where test_tbl.id=tmp.id;

   注意:这种方法需要用户有temporary 表的create 权限。

4、使用mysql 自带的语句构建批量更新

    mysql 实现批量 可以用点小技巧来实现:

    UPDATE yoiurtable
        SET dingdan = CASE id 
            WHEN 1 THEN 3 
            WHEN 2 THEN 4 
            WHEN 3 THEN 5 
        END
    WHERE id IN (1,2,3)

    这句sql 的意思是,更新dingdan 字段,如果id=1 则dingdan 的值为3,如果id=2 则dingdan 的值为4……
    where部分不影响代码的执行,但是会提高sql执行的效率。确保sql语句仅执行需要修改的行数,这里只有3条数据进行更新,而where子句确保只有3行数据执行。   

    例子:UPDATE book
        SET Author = CASE id 
            WHEN 1 THEN '黄飞鸿' 
            WHEN 2 THEN '方世玉'
            WHEN 3 THEN '洪熙官'
        END
    WHERE id IN (1,2,3)

    如果更新多个值的话,只需要稍加修改:

    UPDATE categories      
        SET dingdan = CASE id 
            WHEN 1 THEN 3 
            WHEN 2 THEN 4 
            WHEN 3 THEN 5 
        END, 
        title = CASE id 
            WHEN 1 THEN 'New Title 1'
            WHEN 2 THEN 'New Title 2'
            WHEN 3 THEN 'New Title 3'
        END
    WHERE id IN (1,2,3)

   例子:UPDATE book
        SET Author = CASE id 
            WHEN 1 THEN '黄飞鸿2' 
            WHEN 2 THEN '方世玉2'
            WHEN 3 THEN '洪熙官2'
        END,
        Code = CASE id 
            WHEN 1 THEN 'HFH2' 
            WHEN 2 THEN 'FSY2'
            WHEN 3 THEN 'HXG2'
        END
    WHERE id IN (1,2,3)

    到这里,已经完成一条mysql语句更新多条记录了。

    好了,很有用,记录下来,具体的Book的表结构不写了,大家可以建立自己的表结构,字段改成自己的字段就可以了。MySql是挺好用的。

MySQL 自4.1版以后开始支持INSERT … ON DUPLICATE KEY UPDATE语法,使得原本需要执行3条SQL语句(SELECT,INSERT,UPDATE),缩减为1条语句即可完成。

例如ipstats表结构如下:

 代码如下复制代码
CREATE TABLE ipstats (
ip VARCHAR(15) NOT NULL UNIQUE,
clicks SMALLINT(5) UNSIGNED NOT NULL DEFAULT '0'
);

原本需要执行3条SQL语句,如下:

 代码如下复制代码
IF (SELECT * FROM ipstats WHERE ip='192.168.0.1') {
    UPDATE ipstats SET clicks=clicks+1 WHERE ip='192.168.0.1';
} else {
    INSERT INTO ipstats (ip, clicks) VALUES ('192.168.0.1', 1);
}

而现在只需下面1条SQL语句即可完成:

 代码如下复制代码
INSERT INTO ipstats VALUES('192.168.0.1', 1) ON DUPLICATE KEY UPDATE clicks=clicks+1;

注意,要使用这条语句,前提条件是这个表必须有一个唯一索引或主键。

总结如下:

1.如果表中不存在主键记录,replace和insert*update都与insert是一样的特点。
2.如 果表中存在主键记录,replace相当于执行delete 和 insert两条操作,而insert*update的相当于执行if exist do update else do insert操作。因此,如果replace填充的字段不全,则会导致未被更新的字段都会修改为默认值,并且如果有自增id的话,自增id会变化为最新的 值(这样如果是以自增id为标志的话可能导致记录丢失);而insert*update只是更新部分字段,对于未被更新的字段不会变化(不会强制修改为默 认值)。
 

多条记录操作:

 代码如下复制代码
insert into t(a,b,c) values ('a1','b1','c1'),('a2','b2','c2')

on duplicate key update t.c=values(t.c)

前言

编辑

    我们在实际业务场景中,经常会有一个这样的需求,插入某条记录,如果已经存在了则更新它如果更新日期或者某些列上的累加操作等,我们肯定会想到使用INSERT ... ON DUPLICATE KEY UPDATE语句,一条语句就搞定了查询是否存在和插入或者更新这几个步骤,但是使用这条语句在msyql的innodb5.0以上版本有很多的陷阱,即有可能导致death lock死锁也有可能导致主从模式下的replication产生数据不一致。

正文

    正如前言说的那样,在实际业务中,曾经有过一个需求就是插入一条业务数据,如果不存在则新增,存在则累加更新某一个字段的值,于是乎就想到了使用insert... on duplicate key update这个语句,但是有一天去测试环境查看错误日志时,却发现了在多个事务并发执行同一条insert...on duplicate key update 语句时,也就是insert的内容相同时,发生 了死锁。

  对于insert...on duplicate key update这个语句会引发dealth lock问题,官方文档也没有相关描述,只是进行如下描述:

An INSERT ... ON DUPLICATE KEY UPDATE statement against a table having more than one unique or primary key is also marked as unsafe. (Bug #11765650, Bug #58637)

也就是如果一个表定义有多个唯一键或者主键时,是不安全的,这又引发了以一个问题,见https://bugs.mysql.com/bug.php?id=58637

也就是

     当mysql执行INSERT ON DUPLICATE KEY的 INSERT时,存储引擎会检查插入的行是否会产生重复键错误。如果是的话,它会将现有的
行返回给mysql,mysql会更新它并将其发送回存储引擎。当表具有多个唯一或主键时,此语句对存储引擎检查密钥的顺序非常敏感。根据这个顺序,
存储引擎可以确定不同的行数据给到mysql,因此mysql可以更新不同的行。存储引擎检查key的顺序不是确定性的。例如,InnoDB按照索引添加到
表的顺序检查键。

     insert ... on duplicate key 在执行时,innodb引擎会先判断插入的行是否产生重复key错误,如果存在,在对该现有的行加上S(共享锁)锁,如果返回该行数据给mysql,然后mysql执行完duplicate后的update操作,然后对该记录加上X(排他锁),最后进行update写入。

    如果有两个事务并发的执行同样的语句,那么就会产生death lock,如:

具体的bug描述见:https://bugs.mysql.com/bug.php?id=52020

https://bugs.mysql.com/bug.php?id=58637

编辑

https://bugs.mysql.com/bug.php?id=21356

解决办法:

1、尽量不对存在多个唯一键的table使用该语句

2、在有可能有并发事务执行的insert 的内容一样情况下不使用该语句

 


http://chatgpt.dhexx.cn/article/Sw3R1cn3.shtml

相关文章

MySQL批量更新的四种方法

最近做一个需求,更新3w条数据,一个一个update去更新的,结果花了80分钟,这样性能上很差,也容易阻塞,所以就找了一些MySQL批量更新的方式,在此记录一下 方法一;replace into 这种更新…

Mybatis之批量更新数据(批量update)

前言 当我们使用mybatis的时候,可能经常会碰到一批数据的批量更新问题,因为如果一条数据一更新,那每一条数据就需要涉及到一次数据库的操作,包括网络IO以及磁盘IO,可想而知,这个效率是非常低下的。而平时我…

List和Set之间的转换:达到集合元素去重复

在项目中看到一段代码&#xff1a; return new ArrayList<>(new HashSet<LabelEnum>(list)); 当时我的表情是这样的&#xff1a; 这把list作为构造参数创建新的集合来返回是要做什么&#xff0c;这里的list也是ArrayList集合&#xff0c;这样绕了一圈返回…

【JAVA】List转Set并按照List的顺序排序,HashSet、LinkedHashSet、TreeSet元素保存顺序List转换对比

话不多说 直接代码测试效果: // 简化代码 直接 数组转list 就不用 写很多add了 哈哈哈 String[] array {"f","a","r","q","b","e","o","z","v","p","g"};//…

java中Stream的使用以及List转set和map方法

Stream流的作用&#xff1a; 非常精简方便的去遍历集合实现过滤&#xff0c;排序等。 图解&#xff1a; 例&#xff1a; ArrayList<User> users new ArrayList<>();User user1 new User("赵六",33);users.add(new User("张三",12));users…

JAVA创建对象全过程详解

java世界里面对象无处不在&#xff0c;拿在创建对象的时候都经过哪些步骤&#xff1f; 总结下来大概分为这几步。 对象创建的过程(new 对象的时候) 判断类有没有被加载如果没有(就开始加载类(就是类的加载过程))初始化 &#xff1a;就是给一些变量进行初始化。设置对象头(比较…

Java对象的创建和使用

目录 1、类和对象 2、类的定义方式 3、对象的创建语法 4、什么是实例变量&#xff1f; 5、引用传递的本质 6、引用既可以是局部变量&#xff0c;也可以是成员变量。 7、在一个类的方法中&#xff0c;也可以new本类。 8、NullPointerException&#xff08;空指针异常&…

Java创建对象的方式

Java创建对象的五种方式&#xff1a; &#xff08;1&#xff09;使用new关键字 &#xff08;2&#xff09;使用Object类的clone方法 &#xff08;3&#xff09;使用Class类的newInstance方法 &#xff08;4&#xff09;使用Constructor类中的newInstance方法 &#xff08;5&am…

Java创建对象的几种方式

java是一种面向对象语言,所以我们在写代码过程中会创建很多对象,那java创建的对象到底有多少种呢?其中每种的差别又有哪些呢?请允许我慢慢道来 1.使用new关键字 这是最常见也是使用最多的一种。 Test test = new Test();// 无参构造函数 如果我们想要在创建对象的时候,…

java 之创建对象

文章目录 前言创建对象new关键字的作用构造方法什么是初始化构造方法的作用构造方法的两种形式参考引用 前言 这是我学习过程中做的总结&#xff0c;如有不对见谅。 创建对象 我们用Demo类来创建一个对象。 Demo demonew Demo();这一条语句&#xff0c;其实包括了四个动作&a…

Java中创建对象的5种方法

将会列举5种方法去创建 Java 对象&#xff0c;以及他们如何与构造函数交互&#xff0c;并且会有介绍如何去使用这些方法的示例。 作为一个 Java 开发人员&#xff0c;我们每天都会创建大量的 Java 对象&#xff0c;但是我们通常会使用依赖管理系统去创建这些对象&#xff0c;例…

Java创建对象的四种方式

1. new 2. clone 3. 通过反射newInstance 4. 反序列化 5. String s “abc”&#xff08;这个是比较特殊的&#xff09; 以String类为例 String string null; Class class1 String.class;// 该方法最为安全可靠&#xff0c;程序性能更高。 Class class2 string.getClass(…

c# Topshelf创建linux与Windows服务

目录 Topshelf安装Topshelf包代码如下&#xff0c;简单粗暴卸载服务安装服务 Topshelf 讨厌创建.net 服务时的窗体怎么办&#xff1f;讨厌调试.net服务怎么办?调试.net服务还要自己建控制台怎么办? Topshelf 它来了&#xff01;&#xff01;&#xff01; Topshelf 是一个开源…

htop与top命令

安装htop yum -y install htop htop 类似于 top 命令&#xff0c;但可以让你在垂直和水平方向上滚动&#xff0c;所以你可以看到系统上运行的所有进程&#xff0c;以及他们完整的命令行。可以不用输入进程的 PID 就可以对此进程进行相关的操作 (killing, renicing)。 与 Lin…

使用Quartz.net实现多线程任务定时执行,动态配置Job,结合Topshelf构建Windows服务

几个月前有这么个需求&#xff1a;需要执行一些Job&#xff0c;这些Job会各自按照不同的时间频次执行&#xff0c;且它们做的事情也不同&#xff0c;有的是监控站点&#xff0c;有的是监控服务器存储情况&#xff0c;有的是监控报表PROCEDURE的执行状况… OK&#xff0c;当看到…

top命令参数详解

简介 top命令是Linux下常用的性能分析工具&#xff0c;能够实时显示系统中各个进程的资源占用状况&#xff0c;类似于Windows的任务管理器。 top显示系统当前的进程和其他状况,是一个动态显示过程,即可以通过用户按键来不断刷新当前状态.如果在前台执行该命令,它将独占前台,直…

top命令参数详解(linux top命令的用法详细详解)

通过top命令可以有效的发现系统的缺陷出在哪里。是内存不够、CPU处理能力不够、IO读写过高。 top命令输出长这样&#xff1a; top命令参数详解&#xff08;linux top命令的用法详细详解&#xff09; 以下解析一下各个字段的意思&#xff1a; VIRT&#xff1a;virtual memory …

Topas命令详解

执行topas命令后如图所示&#xff1a; #topas 操作系统的最全面动态&#xff0c;而又查看方便的性能视图就是topas命令了&#xff0c;下面以topas输出为例&#xff0c;对AIX系统的性能监控做简要描述&#xff0c;供运维工程师和系统管理员们参考。 另&#xff1a;1.操作系统报…

Topshelf 打包部署Windows服务

1 创建项目(例&#xff1a;控制台程序) Nuget 引入Topshelf类库 using System; using System.Threading; using System.Threading.Tasks; using Topshelf;namespace LoginTypeInherit {public class Program{private static readonly log4net.ILog log log4net.LogManager.G…

Linux top命令参数详解

Linux top命令参数详解 生产环境系统运行慢&#xff0c;出现无法响应通常原因主要还在于分析CPU、内存、磁盘使用率情况&#xff0c;并结合命令查找出具体进程&#xff0c;并在进程中进一步分析主要因子情况&#xff0c;渗透到对于其中包含线程占用情况的分析。一般而言对于ja…