前言
近期在刷新生产环境数据库的时候,需要更新表中的字段,如果对每条数据结果都执行一次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
输出结果:
搜索函数
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
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']) "UPDATE " . $tableName . " SET "; $sets = []; $bindings = []; foreach ($updateColumn as $uColumn) { $setSql = "`" . $uColumn . "` = CASE "; foreach ($multipleData as $data) { $setSql .= "WHEN `" . $referenceColumn . "` = "; $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('", ") . " 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的使用技巧请查看下面的相关链接
免责声明:本站文章均来自网站采集或用户投稿,网站不提供任何软件下载或自行开发的软件! 如有用户或公司发现本站内容信息存在侵权行为,请邮件告知! 858582#qq.com
更新日志
- 《叶倩文 真心真意过一生》[WAV+CUE][400MB]
- 潘越云.1985-世间女子(滚石25周年经典复刻版)【滚石】【WAV+CUE】
- 陈柏宇.2009-CANT.BE.HALF【SONY】【WAV+CUE】
- 李明依.1989-小女生【滚石】【WAV+CUE】
- 《李荣浩 新时代创作新人王》[WAV分轨][310MB]
- 《黑鸭子与马头琴 史上最动听草原音乐》[WAV+CUE][320MB]
- 《汽车发烧音乐精选CD18》[FLAC+CUE][7.1G]
- 郑希怡.2004-Perfect.Date【英皇娱乐】【FLAC分轨】
- 群星.1994-宝丽金超级孖宝2CD【宝丽金】【WAV+CUE】
- 林忆莲.2019-0(2023精装版)【环球】【WAV+CUE】
- Supper.Moment.2016-The.Moment【寰亚】【FLAC分轨】
- 范莉丝.1979-送郎一朵牵牛花(LP版)【大联机构】【WAV+CUE】
- 刘宇.2024-宇宙诗人【哔哟哔哟文化】【FLAC分轨】
- 《全景声白噪音》沉浸式大自然助眠 带你听自然的声音[mp3]
- 纯音入心系列纯音乐《古筝精选 十指弹一赏心曲一心奏出世人心》1CD[MP3][582MB]