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分页显示制作详细讲解
Dec 05 PHP
php目录管理函数小结
Sep 10 PHP
MySql 按时间段查询数据方法(实例说明)
Nov 02 PHP
PHP mail 通过Windows的SMTP发送邮件失败的解决方案
May 27 PHP
PHP验证码函数代码(简单实用)
Sep 29 PHP
ThinkPHP之getField详解
Jun 20 PHP
分享五个PHP7性能优化提升技巧
Dec 07 PHP
php支付宝在线支付接口开发教程
Sep 19 PHP
PHP那些琐碎的知识点(整理)
May 20 PHP
Laravel框架中自定义模板指令总结
Dec 17 PHP
php在windows环境下获得cpu内存实时使用率(推荐)
Feb 08 PHP
laravel 获取某个查询的查询SQL语句方法
Oct 12 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递归遍历指定目录的文件并统计文件数量的方法
2015/03/24 PHP
PHP生成条形码大揭秘
2015/09/24 PHP
Javascript 的addEventListener()及attachEvent()区别分析
2009/05/21 Javascript
javascript 检测浏览器类型和版本的代码
2009/09/15 Javascript
JS与框架页的操作代码
2010/01/17 Javascript
使用Firebug对js进行断点调试的图文方法
2011/04/02 Javascript
js实现鼠标划过给div加透明度的方法
2015/05/25 Javascript
JS实现图片局部放大或缩小的方法
2016/08/20 Javascript
微信小程序 二维码canvas绘制实例详解
2017/01/06 Javascript
详解vue-router 2.0 常用基础知识点之router-link
2017/05/10 Javascript
nodejs发送http请求时遇到404长时间未响应的解决方法
2017/12/10 NodeJs
JS实现在线ps功能详解
2019/07/31 Javascript
JS函数参数的传递与同名参数实例分析
2020/03/16 Javascript
mpvue网易云短信接口实现小程序短信登录的示例代码
2020/04/03 Javascript
微信小程序中target和currentTarget的区别小结
2020/11/06 Javascript
[57:22]2018DOTA2亚洲邀请赛 4.7总决赛 LGD vs Mineski 第五场
2018/04/10 DOTA
python学习之第三方包安装方法(两种方法)
2015/07/30 Python
浅谈Python爬取网页的编码处理
2016/11/04 Python
Python中is与==判断的区别
2017/03/28 Python
python 产生token及token验证的方法
2018/12/26 Python
django drf框架中的user验证以及JWT拓展的介绍
2019/08/12 Python
python实现全排列代码(回溯、深度优先搜索)
2020/02/26 Python
django 链接多个数据库 并使用原生sql实现
2020/03/28 Python
Python基于argparse与ConfigParser库进行入参解析与ini parser
2021/02/02 Python
Html5 new XMLHttpRequest()监听附件上传进度
2021/01/14 HTML / CSS
Right-on官方网站:日本知名的休闲服装品牌
2019/07/12 全球购物
西班牙在线药店:DosFarma
2020/03/28 全球购物
英国儿童设计师服装和玩具购物网站:Zac & Lulu
2020/10/19 全球购物
经典c++面试题四
2015/05/14 面试题
骨干教师培训感言
2014/01/16 职场文书
自我鉴定注意事项
2014/01/19 职场文书
高中生班主任评语
2014/04/25 职场文书
行政专员求职信范文
2014/05/03 职场文书
小学生三分钟演讲稿
2014/08/18 职场文书
医生个人自我剖析材料
2014/10/08 职场文书
企业党的群众路线教育实践活动学习心得体会
2014/10/31 职场文书