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 相关文章推荐
模仿OSO的论坛(二)
Oct 09 PHP
PHP EOT定界符的使用详解
Sep 30 PHP
php堆排序(heapsort)练习
Nov 13 PHP
php简单实现无限分类树形列表的方法
Mar 27 PHP
php集成套件服务器xampp安装使用教程(适合第一次玩PHP的新手)
Jun 03 PHP
WordPress中用于获取文章作者与分类信息的方法整理
Dec 17 PHP
PHP中Cookie的使用详解(简单易懂)
Apr 28 PHP
php批量删除操作(数据访问)
May 23 PHP
浅谈PHP发送HTTP请求的几种方式
Jul 25 PHP
ubutu 16.04环境下,PHP与mysql数据库,网页登录验证实例讲解
Jul 20 PHP
thinkPHP5框架auth权限控制类与用法示例
Jun 12 PHP
Laravel框架运行出错提示RuntimeException No application encryption key has been specified.解决方法
Apr 02 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;)各种使用方法实例详解
2014/03/20 PHP
destoon调用discuz论坛中带图片帖子的实现方法
2014/08/21 PHP
jQuery中die()方法用法实例
2015/01/19 Javascript
jquery中EasyUI实现异步树
2015/03/01 Javascript
JavaScript中使用Callback控制流程介绍
2015/03/16 Javascript
在JavaScript中访问字符串的子串
2015/07/07 Javascript
WebGL利用FBO完成立方体贴图效果完整实例(附demo源码下载)
2016/01/26 Javascript
JavaScript  cookie 跨域访问之广告推广
2016/04/20 Javascript
jQuery实现带延时功能的水平多级菜单效果【附demo源码下载】
2016/09/21 Javascript
JavaScript构建自己的对象示例
2016/11/29 Javascript
jQuery绑定事件方法及区别(bind,click,on,live,one)
2017/08/14 jQuery
React Native中TabBarIOS的简单使用方法示例
2017/10/13 Javascript
Vue-router路由判断页面未登录跳转到登录页面的实例
2017/10/26 Javascript
vue.extend实现alert模态框弹窗组件
2018/04/28 Javascript
css配合JavaScript实现tab标签切换效果
2018/10/11 Javascript
jquery的$().each和$.each的区别
2019/01/18 jQuery
Flutter实现仿微信底部菜单栏功能
2019/09/18 Javascript
解决vue使用vant下拉框van-dropdown-item 绑定title值不变问题
2020/08/05 Javascript
[03:42]2014DOTA2西雅图国际邀请赛7月9日TOPPLAY
2014/07/09 DOTA
Python文件右键找不到IDLE打开项解决办法
2015/06/08 Python
python实现域名系统(DNS)正向查询的方法
2016/04/19 Python
python学习之面向对象【入门初级篇】
2017/01/21 Python
Python编程快速上手——选择性拷贝操作案例分析
2020/02/28 Python
浅谈numpy中函数resize与reshape,ravel与flatten的区别
2020/06/18 Python
Django model重写save方法及update踩坑详解
2020/07/27 Python
pycharm如何设置官方中文(如何汉化)
2020/12/29 Python
什么造成了Java里面的异常
2016/04/24 面试题
汽车专业毕业生自荐信
2013/11/03 职场文书
申报职称专业技术个人的自我评价
2013/12/12 职场文书
一年级数学教学反思
2014/02/01 职场文书
小学生期末评语大全
2014/04/21 职场文书
学校领导班子四风问题整改意见
2014/10/02 职场文书
手机被没收的检讨书
2014/10/04 职场文书
恰同学少年观后感
2015/06/08 职场文书
python读取pdf格式文档的实现代码
2021/04/01 Python
正确使用MySQL update语句
2021/05/26 MySQL