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 相关文章推荐
一键删除顽固的空文件夹 软件下载
Jan 26 PHP
php empty函数 使用说明
Aug 10 PHP
frename PHP 灵活文件命名函数 frename
Sep 09 PHP
php 抽象类的简单应用
Sep 06 PHP
php在服务器执行exec命令失败的解决方法
Mar 03 PHP
php输出xml格式字符串(用的这个)
Jul 12 PHP
PHP中include与require使用方法区别详解
Oct 19 PHP
常用的php图片处理类(水印、等比缩放、固定高宽)分享
Jun 19 PHP
PHP的swoole扩展安装方法详细教程
May 18 PHP
Yii框架弹出窗口组件CJuiDialog用法分析
Jan 07 PHP
PHP删除二维数组中相同元素及数组重复值的方法示例
May 05 PHP
Laravel修改验证提示信息为中文的示例
Oct 23 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
PHP5在Apache下的两种模式的安装
2006/09/05 PHP
php如何调用webservice应用介绍
2012/11/24 PHP
PHP date函数常用时间处理方法
2015/05/11 PHP
PHP对象相关知识总结
2017/04/09 PHP
IE 下的只读 innerHTML
2009/08/21 Javascript
JavaScript 变量基础知识
2009/11/07 Javascript
extjs ColumnChart设置不同的颜色实现代码
2013/05/17 Javascript
jQuery trigger()方法用法介绍
2015/01/13 Javascript
javascript算法题:求任意一个1-9位不重复的N位数在该组合中的大小排列序号
2015/04/01 Javascript
js停止冒泡和阻止浏览器默认行为的简单方法
2016/05/15 Javascript
修改js confirm alert 提示框文字的简单实例
2016/06/10 Javascript
谈谈对JavaScript原生拖放的深入理解
2016/09/20 Javascript
babel基本使用详解
2017/02/17 Javascript
javaScript 逻辑运算符使用技巧整理
2017/05/03 Javascript
详解Webpack DLL用法以及功能
2017/07/11 Javascript
详解Vue webapp项目通过HBulider打包原生APP(vue+webpack+HBulider)
2019/02/02 Javascript
前端使用crypto.js进行加密的函数代码
2020/08/16 Javascript
vue pages 多入口项目 + chainWebpack 全局引用缩写说明
2020/09/21 Javascript
Python下使用Psyco模块优化运行速度
2015/04/05 Python
Python机器学习之SVM支持向量机
2017/12/27 Python
Python中property属性实例解析
2018/02/10 Python
对Python中Iterator和Iterable的区别详解
2018/10/18 Python
python添加菜单图文讲解
2019/06/04 Python
idea2020手动安装python插件的实现方法
2020/07/17 Python
通俗易懂了解Python装饰器原理
2020/09/17 Python
纯CSS3实现的8种Loading动画效果
2014/07/05 HTML / CSS
小学中秋节活动方案
2014/02/06 职场文书
消防安全承诺书
2014/05/22 职场文书
商铺门前三包责任书
2014/07/25 职场文书
交通事故和解协议书
2014/09/25 职场文书
小学生毕业评语
2014/12/26 职场文书
合作与交流自我评价
2015/03/09 职场文书
学生会工作感言
2015/08/07 职场文书
如何让vue长列表快速加载
2021/03/29 Vue.js
mysql获取指定时间段中所有日期或月份的语句(不设存储过程,不加表)
2021/06/18 MySQL
nginx代理实现静态资源访问的示例代码
2022/07/07 Servers