• MySql中4种批量更新的方法(主要使用1,2)


    https://blog.csdn.net/h330531987/article/details/79114563

    如果是更新为同样的内容,没啥难度,直接在where里面下功夫就好了,大家都懂,我要说的是针对更新内容不一样的情况

    首先,先看看网上转载的方法:

    mysql 批量更新如果一条条去更新效率是相当的慢, 循环一条一条的更新记录,一条记录update一次,这样性能很差,也很容易造成阻塞。

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

    1、 replace into 批量更新

    replace into 表名l (id,字段1) values (1,'2'),(2,'3'),...(x,'y');

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

    insert into 表名l (id,字段1) values (1,'2'),(2,'3'),...(x,'y') on duplicate key update 字段1=values(字段1);

    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行数据执行。

    例子:
    1.  
      UPDATE book
    2.  
      SET Author = CASE id
    3.  
      WHEN 1 THEN '黄飞鸿'
    4.  
      WHEN 2 THEN '方世玉'
    5.  
      WHEN 3 THEN '洪熙官'
    6.  
      END
    7.  
      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)
    复制代码

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

    php中用数组形式赋值批量更新的代码:

    复制代码
    $display_order = array( 
        1 => 4, 
        2 => 1, 
        3 => 2, 
        4 => 3, 
        5 => 9, 
        6 => 5, 
        7 => 8, 
        8 => 9 
    ); 
    $ids = implode(',', array_keys($display_order)); 
    $sql = "UPDATE categories SET display_order = CASE id "; 
    foreach ($display_order as $id => $ordinal) { 
        $sql .= sprintf("WHEN %d THEN %d ", $id, $ordinal); 
    } 
    $sql .= "END WHERE id IN ($ids)"; 
    echo $sql;
    复制代码

    这个例子,有8条记录进行更新。代码也很容易理解,你学会了吗

    更新 100000条数据的性能就测试结果来看,测试当时使用replace into性能较好。

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

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

    相同点:

    (1)没有key的时候,replace与insert .. on deplicate udpate相同。 
    (2)有key的时候,都保留主键值,并且auto_increment自动+1。

    不同点

     有key的时候,replace是delete老记录,而录入新的记录,所以原有的所有记录会被清除,这个时候,如果replace语句的字段不全的话,有些原有的比如例子中c字段的值会被自动填充为默认值。 
      
      而insert .. deplicate update则只执行update标记之后的sql,从表象上来看相当于一个简单的update语句。 
     但是实际上,根据我推测,如果是简单的update语句,auto_increment不会+1,应该也是先delete,再insert的操作,只是在insert的过程中保留除update后面字段以外的所有字段的值。

     所以两者的区别只有一个,insert .. on deplicate udpate保留了所有字段的旧值,再覆盖然后一起insert进去,而replace没有保留旧值,直接删除再insert新值。 
      
     从底层执行效率上来讲,replace要比insert .. on deplicate update效率要高,但是在写replace的时候,字段要写全,防止老的字段数据被删除。

    例子

    创建测试表: 注 意 key 为 code :  unique key (code) 

    create table test (auto_id int auto_increment primary key, code int, times int, name VARCHAR(10), unique key (code));
    INSERT INTO `test` (`code`, `times`, `name`) VALUES ('100', 1, 'wo');


    常规的insert into只影响了一行。test表的数据: 

    1、 Replace into … 
    REPLACE into 已经存在的key时:

    REPLACE into `test` (`code`, `times`) VALUES ('100', 1);


    影响了2行。test表的数据: 


    明显, auto_id自增1,name值为空,times则更新为2了。这说明当与key冲突时,replace覆盖相关字段,其它字段填充默认值,可以理解为删除重复key的记录,新插入一条记录,该语句做了 delete + insert 的操作,所以该语句影响了2行。

    REPLACE into 不存在的key时:

    REPLACE into `test` (`code`, `times`, 'name') VALUES (200, 1, '你');


    只影响了一行,相当于只做了insert操作。test表数据: 

    2、 Insert into on duplicate key update 
    已存在的key:

    INSERT INTO `test` (`code`, `times`, `name`) VALUES (200, 2, 'wo') on DUPLICATE key update times = times + 1;


    影响了2行。test表的数据: 


    明显,name不变,times则更新为2了。这说明当与key冲突时,replace覆盖相关字段,其它字段保留原有值,可以理解为删除重复key的记录,新插入一条记录,该语句做了 delete + insert 的操作,所以该语句影响了2行。至于auto_id有没有自增,我们看一下他插入一条不存在的key时,看一下auto_id。如果有自增,下一条记录的auto_id为5,否者为4。

    不存在的key:

    INSERT INTO `test` (`code`, `times`, `name`) VALUES (300, 1, '你') on DUPLICATE key update times = times + 1;


    受影响1行。test表数据: 


    显然,Insert into on duplicate key update已经存在的key时,会自增长key会自增。不存在的key时,相当于只做了insert操作。

    根据上面例子可以发现,结论正如我们在开头所列举的相同点和不同点。

    如果在INSERT语句末尾指定了ON DUPLICATE KEY UPDATE,并且插入行后会导致在一个UNIQUE索引或PRIMARY KEY中出现重复值,则执行旧行UPDATE;如果不会导致唯一值列重复的问题,则插入新行。例如,如果列a被定义为UNIQUE,并且包含值1,则以下 两个语句具有相同的效果:

    1
    2
    3
    4
    INSERT  INTO  TABLE  (a ,b ,c 
    VALUES  )  ON DUPLICATE  KEY  UPDATE c =c 1;

    UPDATE  TABLE  SET c =c 1  WHERE a 1;

         如果行作为新记录被插入,则受影响行的值为1;如果原有的记录被更新,则受影响行的值为2。

         如果你想了解更多关于INSERT INTO .. ON DUPLICATE KEY的功能说明,详见MySQL参考文档:13.2.4. INSERT语法


         现在问题来了,如果INSERT多行记录, ON DUPLICATE KEY UPDATE后面字段的值怎么指定?要知道一条INSERT语句中只能有一个ON DUPLICATE KEY UPDATE,到底他会更新一行记录,还是更新所有需要更新的行。这个问题困扰了我很久了,其实使用VALUES()函数一切问题都解决了。

         举个例子,字段a被定义为UNIQUE,并且原数据库表table中已存在记录(2,2,9)和(3,2,1),如果插入记录的a值与原有记录重复,则更新原有记录,否则插入新行:

    1
    2
    3
    4
    5
    6
    INSERT  INTO  TABLE  (a ,b ,c )  VALUES 
    ,
    ,
    ,
    )
    ON DUPLICATE  KEY  UPDATE b VALUES (b );

         以上SQL语句的执行,发现(2,5,7)中的a与原有记录(2,2,9)发生唯一值冲突,则执行ON DUPLICATE KEY UPDATE,将原有记录(2,2,9)更新成(2,5,9),将(3,2,1)更新成(3,3,1),插入新记录(1,2,3)和(4,8,2)

         注意:ON DUPLICATE KEY UPDATE只是MySQL的特有语法,并不是SQL标准语法!

    还有一种是我偶尔在写临时脚本的时候用的懒方法,实现起来非常简单,速度肯定不如插入的方法,但是比起一条一条更新,效果也相当明显

    就是直接在循环之前启动事务,循环结束后一起提交,省去每次连接数据库,解析SQL语句等时间。(注意:如果量太大,最好还是要分割一下,比如1000条分割一次,分批次提交)

  • 相关阅读:
    BZOJ 1630/2023 Ant Counting 数蚂蚁
    BZOJ 3997 组合数学
    BZOJ 2200 道路与航线
    BZOJ 3181 BROJ
    BZOJ 4011 落忆枫音
    BZOJ 4027 兔子与樱花
    vijos 1741 观光公交
    vijos 1776 关押罪犯
    vijos 1780 开车旅行
    5、异步通知机制
  • 原文地址:https://www.cnblogs.com/hanby/p/15902136.html
Copyright © 2020-2023  润新知