Laravel实现批量更新多条数据


Posted in PHP onApril 06, 2020

前言

近期在刷新生产环境数据库的时候,需要更新表中的字段,如果对每条数据结果都执行一次update语句,占用的数据库资源就会很多,而且速度慢。

因为项目是Laravel框架,Laravel有批量插入的方法,却没有批量更新的方法,没办法只能自己实现。

准备

mysql case…when的用法

MySQL 的 case when 的语法有两种:

简单函数

CASE [col_name] WHEN [value1] THEN [result1]…ELSE [default] END

CASE [col_name] WHEN [value1] THEN [result1]…ELSE [default] END: 枚举这个字段所有可能的值

select id,status '状态值', case status
when 10 then '未开始'
when 20 then '配送中'
when 30 then '已完成'
when 40 then '已取消'
End '状态'
from table

输出结果:

Laravel实现批量更新多条数据

搜索函数

CASE WHEN [expr] THEN [result1]…ELSE [default] END

CASE WHEN [expr] THEN [result1]…ELSE [default] END:搜索函数可以写判断,并且搜索函数只会返回第一个符合条件的值,其他case被忽略

select id,lessee_id '租户ID', case 
when lessee_id <=1 then '自用系统'
when lessee_id >1 then '租用系统'
End '系统分类'
from waybill_base_info

Laravel实现批量更新多条数据

case…when实现数据库的批量更新

更新单列的值

UPDATE base_info SET
 city_id = CASE id
  WHEN 1 THEN 
  WHEN 2 THEN 
  WHEN 3 THEN 
 END
WHERE id IN (1,2,3)

这句sql的意思是,更新city_id 字段:

如果id=1 则city_id 的值为100010,

如果id=2 则 city_id 的值为100011,

如果id=3 则 city_id 的值为100012。

即是将条件语句写在了一起。

这里的where部分不影响代码的执行,但是会提高sql执行的效率。

确保sql语句仅执行需要修改的行数,这里只有3条数据进行更新,而where子句确保只有3行数据执行。

更新多列的值

UPDATE base_info SET
city_id = CASE id
WHEN 1 THEN 100010
WHEN 2 THEN 100011
WHEN 3 THEN 100012
END,
city_name = CASE id
WHEN 1 THEN ‘北京'
WHEN 2 THEN ‘上海'
WHEN 3 THEN ‘广州'
END
WHERE id IN (1,2,3)

不过这个有个缺点 : 要注意的问题是SQL语句的长度,需要考虑程序运行环境所支持的字符串长度,当然这也可以更新mysql的设置来扩展。

Laravel实现批量更新

在model方法中封装该批量更新的方法:

//批量更新
 public function updateBatch($multipleData = [])
 {
  try {
   if (empty($multipleData)) {
    Log::info("批量更新数据为空");
    return false;
   }
   $tableName = $this->table; // 表名
   $firstRow = current($multipleData);

  $updateColumn = array_keys($firstRow);
  // 默认以id为条件更新,如果没有ID则以第一个字段为条件
  $referenceColumn = isset($firstRow['id']) ? 'id' : current($updateColumn);
  unset($updateColumn[0]);
  // 拼接sql语句
  $updateSql = "UPDATE " . $tableName . " SET ";
  $sets = [];
  $bindings = [];
  foreach ($updateColumn as $uColumn) {
   $setSql = "`" . $uColumn . "` = CASE ";
   foreach ($multipleData as $data) {
    $setSql .= "WHEN `" . $referenceColumn . "` = ? THEN ? ";
    $bindings[] = $data[$referenceColumn];
    $bindings[] = $data[$uColumn];
   }
   $setSql .= "ELSE `" . $uColumn . "` END ";
   $sets[] = $setSql;
  }
  $updateSql .= implode(', ', $sets);
  $whereIn = collect($multipleData)->pluck($referenceColumn)->values()->all();
  $bindings = array_merge($bindings, $whereIn);
  $whereIn = rtrim(str_repeat('?,', count($whereIn)), ',');
  $updateSql = rtrim($updateSql, ", ") . " WHERE `" . $referenceColumn . "` IN (" . $whereIn . ")";
  Log::info($updateSql);
  // 传入预处理sql语句和对应绑定数据
  return DB::update($updateSql, $bindings);
 } catch (\Exception $e) {
  return false;
 }
}

在service层拼接需要更新的数据,并调用该函数:

foreach ($taskInfo as $info) {
   $cityId = $info['requirement']['city_ids'];
   //此处省略n行代码
   $cityInfo = ['id' => $dataId[$info['id']]['id'], 'city_id' => $cityId];
   if ($cityInfo) {
    $cityInfos[] = $cityInfo;
   }
  }
  $res = $this->waybillDriverInfoModel->updateBatch($cityInfos);
 }

拼接的批量更新的数组格式为:

$students = [

[‘id' => 1, ‘city_id' => ‘100010'],

[‘id' => 2, ‘city_id' => ‘100011'],

];

生成的SQL语句如下:

UPDATE base_info SET `city_id` = CASE WHEN `id` = 1 THEN 100010 WHEN `id` = 2 THEN 100011 ELSE `city_id` END WHERE `id` IN (1,2)

因为每次只操作20条数据,所以这样拼接的字符串不会太长,符合mysql的字符串长度的要求,解决问题。

本文主要讲解了Laravel实现批量更新多条数据的方法,更多关于Laravel的使用技巧请查看下面的相关链接

PHP 相关文章推荐
PHP4和PHP5共存于一系统
Nov 17 PHP
php实现首页链接查询 友情链接检查的代码
Jan 05 PHP
php foreach 使用&amp;(与运算符)引用赋值要注意的问题
Feb 16 PHP
PHP学习笔记 (1) 环境配置与代码调试
Jun 19 PHP
PHP性能分析工具XHProf安装使用教程
May 13 PHP
smarty模板判断数组为空的方法
Jun 10 PHP
简介WordPress中用于获取首页和站点链接的PHP函数
Dec 17 PHP
Joomla开启SEF的方法
May 04 PHP
PHP实现负载均衡下的session共用功能
Apr 17 PHP
PHP FileSystem 文件系统常用api整理总结
Jul 12 PHP
在Laravel中实现使用AJAX动态刷新部分页面
Oct 15 PHP
Laravel5.5 手动分页和自定义分页样式的简单实现
Oct 15 PHP
PHP正则之正向预查与反向预查讲解与实例
Apr 06 #PHP
TP5框架安全机制实例分析
Apr 05 #PHP
TP5框架实现自定义分页样式的方法示例
Apr 05 #PHP
TP5框架model常见操作示例小结【增删改查、聚合、时间戳、软删除等】
Apr 05 #PHP
TP5框架实现签到功能的方法分析
Apr 05 #PHP
TP5框架页面跳转样式操作示例
Apr 05 #PHP
TP5框架实现的数据库备份功能示例
Apr 05 #PHP
You might like
PHP把空格、换行符、中文逗号等替换成英文逗号的正则表达式
2014/05/04 PHP
js操作ajax返回的json的注意问题!
2010/02/23 Javascript
超轻量级的基于jquery的三级展开列表
2011/04/26 Javascript
javascript返回顶部效果(自写代码)
2013/01/06 Javascript
jquery的ajax简单结构示例代码
2014/02/17 Javascript
javascript中expression的用法整理
2014/05/13 Javascript
jQuery on()方法使用技巧详解
2015/04/16 Javascript
浅谈javascript中的闭包
2015/05/13 Javascript
浅谈关于JavaScript API设计的一些建议和准则
2015/06/24 Javascript
bootstrap实现弹窗和拖动效果
2016/01/03 Javascript
全面解析Bootstrap中nav、collapse的使用方法
2016/05/22 Javascript
使用PBFunc在Powerbuilder中支付宝当面付款功能
2016/10/01 Javascript
JavaScript动态数量的文件上传控件
2016/11/18 Javascript
深入理解Javascript箭头函数中的this
2017/02/13 Javascript
Koa2微信公众号开发之消息管理
2018/05/16 Javascript
js实现数据导出为EXCEL(支持大量数据导出)
2020/03/31 Javascript
javascript设计模式 ? 命令模式原理与用法实例分析
2020/04/20 Javascript
[02:07]2017国际邀请赛中国区预选赛直邀战队前瞻
2017/06/23 DOTA
[58:58]2018DOTA2亚洲邀请赛 4.4 淘汰赛 TNC vs VG 第二场
2018/04/05 DOTA
Python如何通过subprocess调用adb命令详解
2017/08/27 Python
Python实现螺旋矩阵的填充算法示例
2017/12/28 Python
Django使用httpresponse返回用户头像实例代码
2018/01/26 Python
pycharm执行python时,填写参数的方法
2018/10/29 Python
python 实现兔子生兔子示例
2019/11/21 Python
python+adb命令实现自动刷视频脚本案例
2020/04/23 Python
python中def是做什么的
2020/06/10 Python
CSS3实现文字描边的2种方法(小结)
2020/02/14 HTML / CSS
TripAdvisor西班牙官方网站:全球领先的旅游网站
2018/01/10 全球购物
情侣吵架检讨书
2014/02/05 职场文书
拉拉队口号
2014/06/16 职场文书
农民工工资保障承诺书
2015/05/04 职场文书
志愿者服务活动总结报告
2015/05/06 职场文书
职工培训工作总结
2015/08/10 职场文书
会计专业自荐信范文
2019/05/22 职场文书
浅谈Redis跟MySQL的双写问题解决方案
2022/02/24 Redis
MySQL的InnoDB存储引擎的数据页结构详解
2022/03/03 MySQL