Laravel实现批量更新多条数据

作者:娜小喵儿~ 时间:2023-10-23 03:23:03 

前言

近期在刷新生产环境数据库的时候,需要更新表中的字段,如果对每条数据结果都执行一次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的使用技巧请查看下面的相关链接

来源:https://blog.csdn.net/qq_28673091/article/details/100534908

标签:Laravel,批量更新
0
投稿

猜你喜欢

  • Python *args和**kwargs用法实例解析

    2023-01-16 18:30:55
  • sql server2005实现数据库读写分离介绍

    2024-01-13 20:46:55
  • python实战串口助手_解决8串口多个发送的问题

    2021-12-07 09:53:51
  • Python pyecharts 数据可视化模块的配置方法

    2022-12-09 06:24:26
  • selenium+python配置chrome浏览器的选项的实现

    2022-06-24 11:56:31
  • Python3标准库glob文件名模式匹配的问题

    2021-08-29 14:00:23
  • Django完整增删改查系统实例代码

    2022-11-13 03:07:27
  • go语言通过反射创建结构体、赋值、并调用对应的操作

    2024-03-16 15:52:47
  • MySQL的一些常用的SQL语句整理

    2024-01-19 06:38:40
  • Go到底能不能实现安全的双检锁(推荐)

    2024-04-26 17:36:49
  • Keras目标检测mtcnn facenet搭建人脸识别平台

    2023-09-28 07:02:01
  • js运动动画的八个知识点

    2024-06-07 15:27:25
  • Javascript非构造函数的继承

    2024-04-10 10:54:14
  • JS预览图像将本地图片显示到浏览器上

    2024-04-18 09:35:21
  • javascript开发中使用onpropertychange,oninput事件解决onchange事件的不足

    2024-04-26 17:14:12
  • Golang 的defer执行规则说明

    2023-07-14 08:31:10
  • Python读取及保存mat文件的注意事项说明

    2022-01-10 13:25:54
  • Python从list类型、range()序列简单认识类(class)【可迭代】

    2022-09-09 14:07:20
  • JavaScript语法约定和程序调试原理解析

    2024-04-18 09:46:22
  • 用python实现监控视频人数统计

    2022-04-03 16:01:31
  • asp之家 网络编程 m.aspxhome.com