laravle按不同条件批量更新不同数据记录一下
laravel中DB类中支持批量插入但是没有批量更新语句
如果当需要批量修改数据时,如果用循环来一条一条更新的话极大的消耗资源
下面为批量更新方法,建议分组执行 一组10-20条记录同时更新
/**
* 批量更新
* @param string $whereColumn 条件字段 最好用id主键
* @param array $rows 批量修改的数据 每一行中必须包含条件列与值 例如 $rows = [['id'=>1,'image'=>'xxx','name'=>'xxx'],['id'=>2,'image'=>'xxx','name'=>'xxx','info'=>'xxxx'],['id'=>3,'其他列1'=>'xxx','其他列2'=>'xxx','其他列3'=>'xxxx']] 每行可修改不同数据
* @return false|int 成功返回影响行数 失败返回false
* @throws \Exception
*/
public function updateBatch(string $whereColumn = 'id', array $rows = [])
{
if (empty($rows)) {
throw new StatusTagException("data_notfound");
}
$tableName = DB::getTablePrefix() . $this->getTable(); // 表名
// 取出所有需要更新的列
$updateColumn = [];
foreach ($rows as $row){
$updateColumn = array_merge($updateColumn,array_keys($row));
}
// 去重复
$updateColumn = array_unique($updateColumn);
// 拼接sql语句
$updateSql = "UPDATE " . $tableName . " SET ";
$sets = [];
$bindings = [];
$isExists = false;
foreach ($updateColumn as $uColumn) {
// 当前列 不等于条件列
if($uColumn!==$whereColumn){
$setSql = "`" . $uColumn . "` = CASE ";
// 记录当前列 在所有行中是否存在
$isExists = false;
foreach ($rows as $row) {
// 判断是否存在 条件列
if(!isset($row[$whereColumn]) or is_null($row[$whereColumn]) or is_array($row[$whereColumn]) or is_object($row[$whereColumn])){
throw new \Exception('缺少条件');
}
// 判断当前数据组 是否存在该修改的列 存在则添加修改 不存在不添加
if(isset($row[$uColumn])){
// 判断数据格式
if(is_array($row[$uColumn])){
$row[$uColumn] = json_encode($row[$uColumn]);
}else if(is_object($row[$uColumn])){
throw new \Exception('格式错误');
}
$setSql .= "WHEN `" . $whereColumn . "` = ? THEN ? ";
// 条件列
$bindings[] = $row[$whereColumn];
// 修改的列 值
$bindings[] = $row[$uColumn];
// 在行中存在
$isExists = true;
}
}
// 当前列在所有行中不存在 抛出异常
if(!$isExists){
throw new \Exception('数据不存在');
}
$setSql .= "ELSE `" . $uColumn . "` END ";
$sets[] = $setSql;
}
}
$updateSql .= implode(', ', $sets);
$whereIn = collect($rows)->pluck($whereColumn)->values()->all();
$bindings = array_merge($bindings, $whereIn);
$whereIn = rtrim(str_repeat('?,', count($whereIn)), ',');
$updateSql = rtrim($updateSql, ", ") . " WHERE `" . $whereColumn . "` IN (" . $whereIn . ")";
//dump([$updateSql,$bindings,$whereIn]);
//throw new StatusTagException('missing_data');
// 传入预处理sql语句和对应绑定数据
return DB::update($updateSql, $bindings);
}
使用示例
$updateSkus = [['id'=>1,'image'=>'xxx','price'=>'xxx'],['id'=>2,'image'=>'xxx','price'=>'xxx','info'=>'xxxx'],['id'=>3,'其他列1'=>'xxx','其他列2'=>'xxx','其他列3'=>'xxxx']]
if (!empty($updateSkus)) {
// 分组更新 每组最大20条
$max = 20;
$endKey = count($updateSkus) -1;
$lsSkus = [];
foreach ($updateSkus as $k=>$sku){
$lsSkus[] = $sku;
if(count($lsSkus) === $max or $k === $endKey){
$num = (new GoodsSku())->updateBatch('id',$lsSkus);
if (empty($num) or $num !== count($lsSkus)) {
// 抛出异常 执行回滚
throw new \Exception('更新失败');
}
$lsSkus = [];
}
}