You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Laravel Query Builder中单次批量更新MySQL的ID-值对

Laravel Eloquent 实现批量更新多条记录

我有一个名为userValues的数组,包含1000条数据,结构如下:

[
   {userId: string; value: number;}
]

目前我通过循环执行1000条单独的更新查询,示例代码如下:

public function __construct(
    private DatabaseManager $db   
)

public function example(): void
{
      // 示例仅展示一条数据,实际场景中数组会包含大量条目
      $userValues = [
        (object)[
            'userId' => '34k4j32k34j0',
            'value' => 32423
        ],
      ];

      foreach ($userValues as $el) {
          $this->db->table('users')
              ->where('id', '=', $el->userId)
              ->update([
                  'value' => $el->value,
              ]);
      }
}

这种方式需要向数据库发送N次单独请求,性能极差。我不想遍历数组执行单条更新,希望合并为一条类似以下的语句:

update users set value=1 where id = 1;
update users set value=223322 where id = 2;
-- 以此类推处理所有数组条目

请问如何使用Laravel的Eloquent查询构建器实现这一需求?


方法一:使用CASE WHEN生成单条更新语句(推荐)

这是性能最优的方案,仅需一次数据库请求,利用SQL的CASE WHEN语法批量更新不同记录:

public function batchUpdateUsers(array $userValues): void
{
    if (empty($userValues)) {
        return;
    }

    $caseSegments = [];
    $bindings = [];
    $userIds = [];

    foreach ($userValues as $item) {
        $caseSegments[] = 'WHEN id = ? THEN ?';
        $bindings[] = $item->userId;
        $bindings[] = $item->value;
        $userIds[] = $item->userId;
    }

    $caseStatement = implode(' ', $caseSegments);

    $this->db->table('users')
        ->whereIn('id', $userIds)
        ->update([
            'value' => \DB::raw("CASE $caseStatement ELSE value END")
        ], $bindings);
}

关键说明

  • 生成的SQL为UPDATE users SET value = CASE WHEN id = ? THEN ? ... ELSE value END WHERE id IN (?, ?, ...),一次性完成所有目标记录的更新。
  • ELSE value保证未匹配的记录value字段不会被修改,避免意外更新。
  • whereIn限定更新范围,避免全表扫描,进一步提升执行效率。

方法二:执行多语句更新(需配置支持)

如果需要生成多条独立的UPDATE语句并合并执行,可以使用statement方法,但要确保数据库允许多语句执行(比如MySQL需开启PDO::MYSQL_ATTR_MULTI_STATEMENTS):

public function batchUpdateUsers(array $userValues): void
{
    if (empty($userValues)) {
        return;
    }

    $sqlParts = [];
    $bindings = [];

    foreach ($userValues as $item) {
        $sqlParts[] = 'UPDATE users SET value = ? WHERE id = ?;';
        $bindings[] = $item->value;
        $bindings[] = $item->userId;
    }

    $fullSql = implode(' ', $sqlParts);
    $this->db->statement($fullSql, $bindings);
}

注意事项

  • 部分数据库或安全配置会禁用多语句执行,防止SQL注入风险,使用前需确认环境支持。
  • 该方案的数据库执行效率略低于CASE WHEN方式,但远优于循环单条请求。

内容的提问来源于stack exchange,提问作者Kristi Jorgji

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 16:45:42