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 相关文章推荐
php模板函数 正则实现代码
Oct 15 PHP
限制ckeditor上传图片文件大小的方法
Nov 15 PHP
用 Composer构建自己的 PHP 框架之构建路由
Oct 30 PHP
php中实现记住密码下次自动登录的例子
Nov 06 PHP
php数组转成json格式的方法
Mar 09 PHP
PHP和Mysql中转UTF8编码问题汇总
Oct 10 PHP
学习php设计模式 php实现观察者模式(Observer)
Dec 09 PHP
PHP获取二维数组中某一列的值集合
Dec 25 PHP
PHP单例模式详解及实例代码
Dec 21 PHP
PHP实现使用DOM将XML数据存入数组的方法示例
Sep 27 PHP
PHP7 mongoDB扩展使用的方法分享
May 02 PHP
php判断数组是否为空的实例方法
May 10 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
thinkphp3.x中变量的获取和过滤方法详解
2016/05/20 PHP
PHP微信支付开发实例
2016/06/22 PHP
js验证表单第二部分
2006/11/25 Javascript
javaScript 读取和设置文档元素的样式属性
2009/04/14 Javascript
Javascript 实用小技巧
2010/04/07 Javascript
用JS实现一个TreeMenu效果分享
2011/08/28 Javascript
javascript object array方法使用详解
2012/12/03 Javascript
实现js保留小数点后N位的代码
2014/11/13 Javascript
JavaScript版的TwoQueues缓存模型
2014/12/29 Javascript
javascript实现dom动态创建省市纵向列表菜单的方法
2015/05/14 Javascript
JavaScript中Function函数与Object对象的关系
2015/12/17 Javascript
浅谈JavaScript 函数参数传递到底是值传递还是引用传递
2016/08/23 Javascript
javascript 中的console.log和弹出窗口alert
2016/08/30 Javascript
使用OPENLAYERS3实现点选的方法
2020/09/24 Javascript
jQuery实现的手动拖动控制进度条效果示例【测试可用】
2018/04/18 jQuery
Node.js中Koa2在控制台输出请求日志的方法示例
2019/05/02 Javascript
JS写滑稽笑脸运动效果
2020/05/28 Javascript
Vue v-for中的 input 或 select的值发生改变时触发事件操作
2020/08/31 Javascript
OpenLayers3实现测量功能
2020/09/25 Javascript
python的id()函数解密过程
2012/12/25 Python
详解Python中的循环语句的用法
2015/04/09 Python
python脚本设置超时机制系统时间的方法
2016/02/21 Python
python生成器与迭代器详解
2019/01/01 Python
实时获取Python的print输出流方法
2019/01/07 Python
Python +Selenium解决图片验证码登录或注册问题(推荐)
2020/02/09 Python
python可迭代对象去重实例
2020/05/15 Python
python 图像判断,清晰度(明暗),彩色与黑白实例
2020/06/04 Python
python两种获取剪贴板内容的方法
2020/11/06 Python
Python导入父文件夹中模块并读取当前文件夹内的资源
2020/11/19 Python
Yahoo-PHP面试题3
2012/01/14 面试题
XMLHttpRequest对象在IE和Firefox中创建方式有没有不同
2016/03/23 面试题
校园安全广播稿
2014/02/08 职场文书
《梅兰芳学艺》教学反思
2014/02/24 职场文书
本溪水洞导游词
2015/02/11 职场文书
2015年青年志愿者工作总结
2015/05/20 职场文书
CSS 伪元素::marker详解
2021/06/26 HTML / CSS