当前位置:首页 > CMS教程 > 其它CMS > 列表

Laravel实现批量更新多条数据

发布:smiling 来源: PHP粉丝网  添加日期:2022-02-25 10:55:14 浏览: 评论:0 

这篇文章主要介绍了Laravel实现批量更新多条数据,需要的朋友可以参考下。

前言:近期在刷新生产环境数据库的时候,需要更新表中的字段,如果对每条数据结果都执行一次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: 枚举这个字段所有可能的值

  1. select id,status '状态值'case status 
  2. when 10 then '未开始' 
  3. when 20 then '配送中' 
  4. when 30 then '已完成' 
  5. when 40 then '已取消' 
  6. End '状态' 
  7. from table 

输出结果:

搜索函数

CASE WHEN [expr] THEN [result1]…ELSE [default] END

CASE WHEN [expr] THEN [result1]…ELSE [default] END:搜索函数可以写判断,并且搜索函数只会返回第一个符合条件的值,其他case被忽略

  1. select id,lessee_id '租户ID'case 
  2. when lessee_id <=1 then '自用系统' 
  3. when lessee_id >1 then '租用系统' 
  4. End '系统分类' 
  5. from waybill_base_info 

case…when实现数据库的批量更新

更新单列的值

  1. UPDATE base_info SET 
  2.  city_id = CASE id 
  3.   WHEN 1 THEN 
  4.   WHEN 2 THEN 
  5.   WHEN 3 THEN 
  6.  END 
  7. 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行数据执行。

更新多列的值

  1. UPDATE base_info SET 
  2. city_id = CASE id 
  3. WHEN 1 THEN 100010 
  4. WHEN 2 THEN 100011 
  5. WHEN 3 THEN 100012 
  6. END
  7. city_name = CASE id 
  8. WHEN 1 THEN ‘北京' 
  9. WHEN 2 THEN ‘上海' 
  10. WHEN 3 THEN ‘广州' 
  11. END 
  12. WHERE id IN (1,2,3) 

不过这个有个缺点 : 要注意的问题是SQL语句的长度,需要考虑程序运行环境所支持的字符串长度,当然这也可以更新mysql的设置来扩展。

Laravel实现批量更新

在model方法中封装该批量更新的方法:

  1. //批量更新 
  2.  public function updateBatch($multipleData = []) 
  3.  { 
  4.   try { 
  5.    if (emptyempty($multipleData)) { 
  6.     Log::info("批量更新数据为空"); 
  7.     return false; 
  8.    } 
  9.    $tableName = $this->table; // 表名 
  10.    $firstRow = current($multipleData); 
  11.  
  12.   $updateColumn = array_keys($firstRow); 
  13.   // 默认以id为条件更新,如果没有ID则以第一个字段为条件 
  14.   $referenceColumn = isset($firstRow['id']) ? 'id' : current($updateColumn); 
  15.   unset($updateColumn[0]); 
  16.   // 拼接sql语句 
  17.   $updateSql = "UPDATE " . $tableName . " SET "
  18.   $sets = []; 
  19.   $bindings = []; 
  20.   foreach ($updateColumn as $uColumn) { 
  21.    $setSql = "`" . $uColumn . "` = CASE "
  22.    foreach ($multipleData as $data) { 
  23.     $setSql .= "WHEN `" . $referenceColumn . "` = ? THEN ? "
  24.     $bindings[] = $data[$referenceColumn]; 
  25.     $bindings[] = $data[$uColumn]; 
  26.    } 
  27.    $setSql .= "ELSE `" . $uColumn . "` END "
  28.    $sets[] = $setSql
  29.   } 
  30.   $updateSql .= implode(', '$sets); 
  31.   $whereIn = collect($multipleData)->pluck($referenceColumn)->values()->all(); 
  32.   $bindings = array_merge($bindings$whereIn); 
  33.   $whereIn = rtrim(str_repeat('?,'count($whereIn)), ','); 
  34.   $updateSql = rtrim($updateSql", ") . " WHERE `" . $referenceColumn . "` IN (" . $whereIn . ")"
  35.   Log::info($updateSql); 
  36.   // 传入预处理sql语句和对应绑定数据 
  37.   return DB::update($updateSql$bindings); 
  38.  } catch (\Exception $e) { 
  39.   return false; 
  40.  } 

在service层拼接需要更新的数据,并调用该函数:

  1. foreach ($taskInfo as $info) { 
  2.   $cityId = $info['requirement']['city_ids']; 
  3.   //此处省略n行代码 
  4.   $cityInfo = ['id' => $dataId[$info['id']]['id'], 'city_id' => $cityId]; 
  5.   if ($cityInfo) { 
  6.    $cityInfos[] = $cityInfo
  7.   } 
  8.  } 
  9.  $res = $this->waybillDriverInfoModel->updateBatch($cityInfos); 

拼接的批量更新的数组格式为:

  1. $students = [ 
  2.  
  3. [‘id' => 1, ‘city_id' => ‘100010'], 
  4.  
  5. [‘id' => 2, ‘city_id' => ‘100011'], 
  6.  
  7. ]; 

生成的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的字符串长度的要求,解决问题。

Tags: Laravel批量更新多条数据

分享到: