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

如果是更新为同样的内容,没啥难度,直接在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行数据执行。

例子:
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)
复制代码

 

到这里,已经完成一条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));
 
 
  • 1
INSERT INTO `test` (`code`, `times`, `name`) VALUES ('100', 1, 'wo');
 
 
  • 1

这里写图片描述 
常规的insert into只影响了一行。test表的数据: 
这里写图片描述

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

REPLACE into `test` (`code`, `times`) VALUES ('100', 1);
 
 
  • 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, '你');
 
 
  • 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;
 
 
  • 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

这里写图片描述 
受影响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  ( 1 , 2 , 3 )  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 
( 1 , 2 , 3 ) ,
( 2 , 5 , 7 ) ,
( 3 , 3 , 6 ) ,
( 4 , 8 , 2 )
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条分割一次,分批次提交)

  • 1
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值