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 相关文章推荐
Smarty结合Ajax实现无刷新留言本实例
Jan 02 PHP
调整优化您的LAMP应用程序的5种简单方法
Jun 26 PHP
探讨:array2xml和xml2array以及xml与array的互相转化
Jun 24 PHP
php常用字符串比较函数实例汇总
Nov 24 PHP
PHP使用Pthread实现的多线程操作实例
Nov 14 PHP
PHP开发中AJAX技术的简单应用
Dec 11 PHP
PHP实现查询两个数组中不同元素的方法
Feb 23 PHP
java微信开发之上传下载多媒体文件
Jun 24 PHP
Laravel接收前端ajax传来的数据的实例代码
Jul 20 PHP
浅谈使用 Yii2 AssetBundle 中 $publishOptions 的正确姿势
Nov 08 PHP
PHP实现压缩图片尺寸并转为jpg格式的方法示例
May 10 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&amp;&amp;mysql)六
2006/10/09 PHP
php+jquery编码方面的一些心得(utf-8 gb2312)
2010/10/12 PHP
用PHP实现 上一篇、下一篇的代码
2012/09/29 PHP
php计算给定日期所在周的开始日期和结束日期示例
2017/02/06 PHP
一个实用的php验证码类
2017/07/06 PHP
自动更新作用
2006/10/08 Javascript
JavaScript 申明函数的三种方法 每个函数就是一个对象(一)
2009/12/04 Javascript
百度判断手机终端并自动跳转js代码及使用实例
2014/06/11 Javascript
Webpack的Loader和Plugin的区别
2020/11/09 Javascript
Python模拟百度登录实例详解
2016/01/20 Python
python如何在循环引用中管理内存
2018/03/20 Python
python 平衡二叉树实现代码示例
2018/07/07 Python
Flask模拟实现CSRF攻击的方法
2018/07/24 Python
pycharm+PyQt5+python最新开发环境配置(踩坑)
2019/02/11 Python
opencv与numpy的图像基本操作
2019/03/08 Python
PyPDF2读取PDF文件内容保存到本地TXT实例
2020/05/12 Python
一文解决django 2.2与mysql兼容性问题
2020/07/15 Python
你应该知道的30个css选择器
2014/03/19 HTML / CSS
html5唤起app的方法
2017/11/30 HTML / CSS
美国最大点评网站:Yelp
2018/02/14 全球购物
POP文化和音乐灵感的时尚:Hot Topic
2019/06/19 全球购物
介绍Ibatis的核心类
2013/11/18 面试题
网络工程师面试(三木通信技术有限公司)
2013/06/05 面试题
js正则匹配markdown里的图片标签的实现
2021/03/24 Javascript
学校经典推荐信
2013/10/30 职场文书
统计员岗位职责
2013/11/14 职场文书
体育节口号
2014/06/19 职场文书
财务统计员岗位职责
2015/04/14 职场文书
个人维稳承诺书
2015/05/04 职场文书
欠款纠纷起诉状
2015/05/19 职场文书
幼儿园六一主持词
2015/06/30 职场文书
2016年母亲节广告语
2016/01/28 职场文书
文明和谐家庭事迹材料(2016精选版)
2016/02/29 职场文书
高中优秀作文(范文)
2019/08/15 职场文书
JavaCV实现照片马赛克效果
2022/01/22 Java/Android
Go获取两个时区的时间差
2022/04/20 Golang