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 (ignore) 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));
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 ( 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条分割一次,分批次提交)
本文作者:韩憨
本文链接:https://www.cnblogs.com/hanby/p/15902136.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步