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 数组的一个悲剧?
May 11 PHP
PHP服务器页面间跳转实现方法
Aug 02 PHP
PHP垃圾回收机制引用计数器概念分析
Jun 24 PHP
ThinkPHP中的三大自动简介
Aug 22 PHP
php项目中百度 UEditor 简单安装调试和调用
Jul 15 PHP
PHP实现简单搜歌的方法
Jul 28 PHP
PHP实现文件上传下载实例
Oct 18 PHP
PHP面向对象程序设计方法实例详解
Dec 24 PHP
PHP实现的简单路由和类自动加载功能
Mar 13 PHP
thinkPHP框架实现生成条形码的方法示例
Jun 06 PHP
php实现大文件断点续传下载实例代码
Oct 01 PHP
php实现JWT验证的实例教程
Nov 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
一个简单计数器的源代码
2006/10/09 PHP
PHP多维数组指定多字段排序的示例代码
2018/05/16 PHP
JSQL 基于客户端的成绩统计实现方法
2010/05/05 Javascript
jquery的$(document).ready()和onload的加载顺序
2010/05/26 Javascript
javascript运行机制之this详细介绍
2014/02/07 Javascript
28个常用JavaScript方法集锦
2015/01/14 Javascript
浅谈Javascript的静态属性和原型属性
2015/05/07 Javascript
JQuery勾选指定name的复选框集合并显示的方法
2015/05/18 Javascript
jQuery实现新消息在网页标题闪烁提示
2015/06/23 Javascript
Spring mvc 接收json对象
2015/12/10 Javascript
基于jquery实现轮播焦点图插件
2016/03/31 Javascript
Javascript实现鼠标框选操作  不是点击选取
2016/04/14 Javascript
jQuery事件绑定on()与弹窗实现代码
2016/04/28 Javascript
AngularJS基础 ng-options 指令详解
2016/08/02 Javascript
微信小程序 图片等比例缩放(图片自适应屏幕)
2016/11/16 Javascript
ES6新特性之变量和字符串用法示例
2017/04/01 Javascript
JavaScript实现获取用户单击body中所有A标签内容的方法
2017/06/05 Javascript
jquery animate动画持续运动的实例
2017/11/29 jQuery
基于jQuery.i18n实现web前端的国际化
2018/05/04 jQuery
vue基本使用--refs获取组件或元素的实例
2019/11/07 Javascript
python实现将内容分行输出
2015/11/05 Python
Python 正则表达式匹配字符串中的http链接方法
2018/12/25 Python
使用Keras预训练好的模型进行目标类别预测详解
2020/06/27 Python
idea2020手动安装python插件的实现方法
2020/07/17 Python
Bibloo匈牙利:女装、男装、童装及鞋子和配饰
2019/04/14 全球购物
英国卫浴商店:Ergonomic Design
2019/09/22 全球购物
琳达·法罗眼镜英国官网:Linda Farrow英国
2021/01/19 全球购物
VC++笔试题
2014/10/13 面试题
实习会计求职自荐信范文
2014/03/10 职场文书
《广玉兰》教学反思
2014/04/14 职场文书
如何撰写一封出色的求职信
2014/04/27 职场文书
服务承诺书怎么写
2014/05/24 职场文书
法英专业大学生职业生涯规划书范文
2014/09/22 职场文书
初中教师德育工作总结2015
2015/05/12 职场文书
三八节活动简报
2015/07/20 职场文书
python缺失值填充方法示例代码
2022/12/24 Python