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
WHEN1THEN3
WHEN2THEN4
WHEN3THEN5
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
WHEN1THEN3
WHEN2THEN4
WHEN3THEN5
END,
title =CASE id
WHEN1THEN'New Title 1'
WHEN2THEN'New Title 2'
WHEN3THEN'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,mysql删除重复的数据保留一条
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 的时候,字段要写全,防⽌⽼的字段数据被删除。
例⼦
常规的insert into 只影响了⼀⾏。test 表的数据: 1、 Replace into …
REPLACE into 已经存在的key
时:
影响了2⾏。test 表的数据:
明显, auto_id ⾃增1,name 值为空,times 则更新为2了。这说明当与key 冲突时,replace 覆盖相关字段,其它字段填充默认值,可以理解为删除重复key 的记录,新插⼊⼀条记录,该语句做了 delete + insert 的操作,所以该语句影响了2⾏。
REPLACE into 不存在的key 时:
create table test (auto_id int auto_increment primary key, code int, times int, name VARCHAR(10), unique key (code));1INSERT INTO `test` (`code`, `times`, `name`) VALUES ('100', 1, 'wo');
1REPLACE into `test` (`code`, `times`) VALUES ('100', 1);1REPLACE into `test` (`code`, `times`, 'name') VALUES (200, 1, '你');
1
只影响了⼀⾏,相当于只做了insert操作。test表数据:
2、 Insert into on duplicate key update
已存在的key :
影响了2⾏。test表的数据:
明显,name不变,times则更新为2了。这说明当与key冲突时,replace覆盖相关字段,其它字段保留原有值,可以理解为删除重复key的记录,新插⼊⼀条记录,该语句做了 delete + insert 的操作,所以该语句影响了2⾏。⾄于auto_id有没有⾃增,我们看⼀下他插⼊⼀条不存在的key时,看⼀下auto_id。如果有⾃增,下⼀条记录的auto_id为5,否者为4。
不存在的key :
受影响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;
INSERT INTO `test` (`code`, `times`, `name`) VALUES (200, 2, 'wo') on DUPLICATE key update times = times + 1; 1
INSERT INTO `test` (`code`, `times`, `name`) VALUES (300, 1, '你') on DUPLICATE key update times = times + 1; 1
如果⾏作为新记录被插⼊,则受影响⾏的值为1;如果原有的记录被更新,则受影响⾏的值为2。
如果你想了解更多关于INSERT INTO .. ON DUPLICATE KEY的功能说明,详见MySQL参考⽂档:
现在问题来了,如果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条分割⼀次,分批次提交)
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论