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 变量定义和变量替换的方法
Jul 30 PHP
php正则过滤html标签、空格、换行符的代码(附说明)
Oct 25 PHP
PHP变量内存分配问题记录整理
Nov 27 PHP
ThinkPHP框架实现session跨域问题的解决方法
Jul 01 PHP
基于php实现随机合并数组并排序(原排序)
Nov 26 PHP
PHP指定截取字符串中的中英文或数字字符的实例分享
Mar 18 PHP
PHP 绘制网站登录首页图片验证码
Apr 12 PHP
Yii列表定义与使用分页方法小结(3种方法)
Jul 15 PHP
PHP基于imagick扩展实现合成图片的两种方法【附imagick扩展下载】
Nov 14 PHP
PHP反射学习入门示例
Jun 14 PHP
浅析PHP反序列化中过滤函数使用不当导致的对象注入问题
Feb 15 PHP
PHP开发api接口安全验证操作实例详解
Mar 26 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设计模式 php实现建造者模式
2015/12/07 PHP
PHP 7.0.2 正式版发布
2016/01/08 PHP
PHP判断文件是否被引入的方法get_included_files用法示例
2016/11/29 PHP
php文件上传类的分享
2017/07/06 PHP
ThinkPHP3.2.3框架邮件发送功能图文实例详解
2019/04/23 PHP
javascript验证身份证号
2015/03/03 Javascript
JQuery记住用户名密码实现下次自动登录功能
2015/04/27 Javascript
检查表单元素的值是否为空的实例代码
2016/06/16 Javascript
H5移动端适配 Flexible方案
2016/10/24 Javascript
AngularJS动态加载模块和依赖的方法分析
2016/11/08 Javascript
jQuery实现隔行变色的方法分析(对比原生JS)
2016/11/18 Javascript
关于javascript事件响应的基础语法总结(必看篇)
2016/12/26 Javascript
vue和react等项目中更简单的实现展开收起更多等效果示例
2018/02/22 Javascript
基于Vue全局组件与局部组件的区别说明
2020/08/11 Javascript
使用Python进行新浪微博的mid和url互相转换实例(10进制和62进制互算)
2014/04/25 Python
python脚本实现统计日志文件中的ip访问次数代码分享
2014/08/06 Python
在Python中处理字符串之ljust()方法的使用简介
2015/05/19 Python
python socket网络编程之粘包问题详解
2018/04/28 Python
python如何给字典的键对应的值为字典项的字典赋值
2019/07/05 Python
pycharm 设置项目的根目录教程
2020/02/12 Python
Python读取xlsx数据生成图标代码实例
2020/08/12 Python
python二维图制作的实例代码
2020/12/03 Python
详解css3 mask遮罩实现一些特效
2018/10/24 HTML / CSS
利用HTML5绘制点线面组成的3D图形的示例
2015/05/12 HTML / CSS
Html5移动端div固定到底部实现底部导航条的几种方式
2021/03/09 HTML / CSS
阿里健康大药房:阿里自营网上药店
2017/08/01 全球购物
澳大利亚儿童鞋在线:The Trybe
2019/07/16 全球购物
俄罗斯在线购买飞机票、火车票、巴士票网站:Tutu.ru
2020/03/16 全球购物
法制报告会主持词
2014/04/02 职场文书
小学生常见病防治方案
2014/06/06 职场文书
本科应届生自荐信
2014/06/29 职场文书
大学社团招新的通讯稿
2014/09/10 职场文书
2015年世界水日活动总结
2015/02/09 职场文书
行政答辩状范文
2015/05/21 职场文书
幼儿园庆元旦主持词
2015/07/06 职场文书
开学典礼致辞
2015/07/29 职场文书