第三选择

刻意练习,日渐精进

0%

批量更新数据库字段

今天在修改项目 bug 的时候,有这么一个场景,需要去同步远程数据库的数据,但是不能确定是要新增还是更新,因此需要每一条进行判断。

一开始做的时候,是在遍历并进行判断以后,针对每一条的接口来执行数据库的插入或更新的操作。(现在看看觉得很蠢,性能太差了)

使用框架进行CURD操作时,每执行一次语句都需要连接一次数据库,并执行优化、分析的操作。因此希望可以尽可能的一次执行多条记录的操作。

批量插入的操作,日常中使用的非常多了,就不多赘述了,主要讲讲批量更新的语法。

因为日常是使用 Laravel 框架的,所以我也封装好了一个方法,有需要的可以直接拿去使用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
public function batchUpdate($updateArray, $conditionColumn, $tableName)
{
if (!updateArray) {
return;
}

// 用第一条数据来获取要更新的字段
$firstRow = current($updateArray);
$columns = array_keys($firstRow);

$sql = 'UPDATE ' . $tableName . ' SET';

$bindings = [];
foreach ($columns as $column) {
$sql .= '`' . $column . '` = CASE `' . $conditionColumn . '` ';
foreach ($updateArray as $item) {
$sql .= 'WHEN ? THEN ? ';
$bindings[] = $item[$conditionColumn];
$bindings[] = $item[$column];
}
$sql .= 'END,';
}
$sql = rtrim($sql, ',');

$whereIn = collect($updateArray)->pluck($conditionColumn)->values()->all();
$bindings = array_merge($bindings, $whereIn);

$whereIn = rtrim(str_repeat('?,', count($whereIn)), ',');
$sql .= ' WHERE `' . $conditionColumn . '` IN (' . $whereIn . ')';

DB::update($sql, $bindings);
}

为了防止 SQL 注入,因此使用了参数绑定的写法。

封装出来的 SQL 语句如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
UPDATE table_name 
SET `column1` =
CASE
`condition_column`
WHEN condition_value1 THEN
update_value1
WHEN condition_value2 THEN
update_value2
END,
`column2` =
CASE
`condition_column`
WHEN condition_value1 THEN
update_value3
WHEN condition_value2 THEN
update_value4
END
WHERE
`condition_column` IN ( condition_value1, condition_value2, condition_value3...)