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.04简明安装
Oct 09 PHP
php操作SVN版本服务器类代码
Nov 27 PHP
PHP警告Cannot use a scalar value as an array的解决方法
Jan 11 PHP
php防注入,表单提交值转义的实现详解
Jun 10 PHP
PHP操作Memcache实例介绍
Jun 14 PHP
php+mysql实现无限分类实例详解
Jan 15 PHP
smarty的section嵌套循环用法示例
May 28 PHP
PHP经典算法集锦【经典收藏】
Sep 14 PHP
Zend Framework数据库操作技巧总结
Feb 18 PHP
PHP实现的杨辉三角求解算法分析
Mar 11 PHP
阿里对象存储OSS在laravel框架中的使用方法
Oct 13 PHP
PHP基于进程控制函数实现多线程
Dec 09 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
用js进行url编码后用php反解以及用php实现js的escape功能函数总结
2010/02/08 PHP
基于pear auth实现登录验证
2010/02/26 PHP
浅谈thinkphp的实例化模型
2015/01/04 PHP
php实现无限级分类(递归方法)
2015/08/06 PHP
JSON用法之将PHP数组转JS数组,JS如何接收PHP数组
2015/10/08 PHP
PHP解压tar.gz格式文件的方法
2016/02/14 PHP
php 人员权限管理(RBAC)实例(推荐)
2017/05/24 PHP
优秀js开源框架-jQuery使用手册(1)
2007/03/10 Javascript
jquery数据验证插件(自制,简单,练手)实例代码
2013/10/24 Javascript
js正则表达exec与match的区别说明
2014/01/29 Javascript
JavaScript学习笔记之内置对象
2015/01/22 Javascript
理解javascript对象继承
2016/04/17 Javascript
jQuery中$.ajax()方法参数解析
2016/10/22 Javascript
浅析JavaScript中break、continue和return的区别
2016/11/30 Javascript
jQueryeasyui 中如何使用datetimebox 取两个日期间相隔的天数
2017/06/13 jQuery
AngularJS实现与后台服务器进行交互的示例讲解
2018/08/13 Javascript
详解vue-cli 3.0 build包太大导致首屏过长的解决方案
2018/11/10 Javascript
使用NestJS开发Node.js应用的方法
2018/12/03 Javascript
vue父组件触发事件改变子组件的值的方法实例详解
2019/05/07 Javascript
[55:56]NB vs Infamous 2019国际邀请赛淘汰赛 败者组 BO3 第二场 8.22
2019/09/05 DOTA
Python编程产生非均匀随机数的几种方法代码分享
2017/12/13 Python
python list格式数据excel导出方法
2018/10/31 Python
Python3.4学习笔记之列表、数组操作示例
2019/03/01 Python
Python利用Scrapy框架爬取豆瓣电影示例
2020/01/17 Python
tensorflow中tf.slice和tf.gather切片函数的使用
2020/01/19 Python
纯CSS3实现漂亮的input输入框动画样式库(Text input love)
2018/12/29 HTML / CSS
如何在发生故障的节点上重新安装 SQL Server
2013/03/14 面试题
商得四方公司面试题(gid+)
2014/04/30 面试题
本科毕业生自荐信
2014/05/26 职场文书
2014中考励志标语
2014/06/05 职场文书
春季运动会开幕词
2015/01/28 职场文书
区域经理岗位职责
2015/02/02 职场文书
技术负责人岗位职责
2015/02/10 职场文书
世界环境日活动总结
2015/02/11 职场文书
2016年第十四个公民道德宣传日活动总
2016/04/01 职场文书
本地搭建minio文件服务器(使用bat脚本启动)的方法
2022/07/15 Servers