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 print类函数使用总结
Jun 25 PHP
PHP url 加密解密函数代码
Aug 26 PHP
将word转化为swf 如同百度文库般阅读实现思路及代码
Aug 09 PHP
PHP如何利用P3P实现跨域
Aug 24 PHP
PHP中使用sleep造成mysql读取失败的案例和解决方法
Aug 21 PHP
php模仿asp Application对象在线人数统计实现方法
Jan 04 PHP
php技术实现加载字体并保存成图片
Jul 27 PHP
php多线程实现方法及用法实例详解
Oct 26 PHP
PHP调用存储过程返回值不一致问题的解决方法分析
Apr 26 PHP
PHP jQuery+Ajax结合写批量删除功能
May 19 PHP
PHP cookie与session会话基本用法实例分析
Nov 18 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
PHPCMS手机站伪静态设置详细教程
2017/02/06 PHP
PHP7.1实现的AES与RSA加密操作示例
2018/06/15 PHP
一些有关检查数据的JS代码
2006/09/07 Javascript
js控制div及网页相关属性的代码
2009/12/19 Javascript
JS图片无缝滚动(简单利于使用)
2013/06/17 Javascript
js实现图片拖动改变顺序附图
2014/05/13 Javascript
使用node.js半年来总结的 10 条经验
2014/08/18 Javascript
点击button获取text内容并改变样式的js实现
2014/09/09 Javascript
js密码强度校验
2015/11/10 Javascript
详解Javascript中的原型OOP
2016/10/12 Javascript
jQuery倒计时代码(超简单)
2017/02/27 Javascript
socket.io学习教程之基础介绍(一)
2017/04/29 Javascript
基于vue2框架的机器人自动回复mini-project实例代码
2017/06/13 Javascript
js合并两个数组生成合并后的key:value数组
2018/05/09 Javascript
Nuxt.js之自动路由原理的实现方法
2018/11/21 Javascript
如何用RxJS实现Redux Form
2018/12/29 Javascript
js判断一个对象是数组(函数)的方法实例
2019/12/19 Javascript
Electron实现应用打包、自动升级过程解析
2020/07/07 Javascript
解决vue打包报错Unexpected token: punc的问题
2020/10/24 Javascript
让Vue响应Map或Set的变化操作
2020/11/11 Javascript
Python 条件判断的缩写方法
2008/09/06 Python
理解Python中的绝对路径和相对路径
2017/08/30 Python
详解Python 数据库的Connection、Cursor两大对象
2018/06/25 Python
使用Python做垃圾分类的原理及实例代码附源码
2019/07/02 Python
python虚拟环境的安装和配置(virtualenv,virtualenvwrapper)
2019/08/09 Python
Python中使用gflags实例及原理解析
2019/12/13 Python
台湾线上百货零售购物平台:friDay购物
2017/08/18 全球购物
override和overload的区别
2016/03/09 面试题
早读迟到检讨书
2014/01/24 职场文书
詹天佑教学反思
2014/04/30 职场文书
政治表现评语
2014/05/04 职场文书
关于感恩的演讲稿200字
2014/08/26 职场文书
高中毕业典礼演讲稿
2014/09/09 职场文书
销售经理工作失职检讨书
2014/10/24 职场文书
如何使用vue3打造一个物料库
2021/05/08 Vue.js
Html5同时支持多端sdk的小技巧
2021/11/17 HTML / CSS