【问题标题】:Laravel Bulk Update for multiple record idsLaravel 批量更新多个记录 id
【发布时间】:2019-01-02 04:14:04
【问题描述】:

我想在 Laravel 中批量更新我的记录,但记录没有更新。我对每个 ID 都有不同的记录。以下是我正在尝试的。

$ids = [5,6,8,9],
$updated_array = [
  ['name' => 'tarun'],
  ['name' => 'Akash'],
  ['name' => 'Soniya'],
  ['name' => 'Shalu'],
];

Model::whereIn('id', $ids)->update($updated_array);

【问题讨论】:

  • 在您的模型中,设置protected $guarded = array(); $fillable$guarded 属性用于启用批量插入和更新

标签: php mysql laravel eloquent


【解决方案1】:

当您尝试将多行更新为相同的值时,会使用大量更新。您不能使用不同的值进行批量更新。

因此,这会起作用,但会将所有匹配的记录更新为“tarun”的名称:

Model::whereIn('id', $ids)->update(['name' => 'tarun']);

对于你的例子,你可以这样做:

foreach($ids as $key => $id) {
    Model::where('id', $id)->update($updated_array[$key]);
}

但据我所知,如果不在 Laravel 中运行 4 个查询并编写原始 SQL 语句来完成此操作,就无法做到这一点,甚至会很麻烦。

【讨论】:

  • 我不想运行 foreach 循环。
  • 为什么不呢?让它变得更难似乎毫无意义,这是一个简单的循环。
  • 如果有10000条记录就会执行10000条。对于一个简单的操作执行10000条查询是否有意义
  • 如果它们都是不同的查询,那么是的。您没有使用相同的值更新它...
【解决方案2】:

这个问题的一些好的解决方案在下面的帖子中:https://github.com/laravel/ideas/issues/575

1) 可以创建自定义函数来执行此操作,该函数使用原始 SQL,根据帖子中的 barryvdh 评论。

    public static function updateValues(array $values)
    {
        $table = MyModel::getModel()->getTable();

        $cases = [];
        $ids = [];
        $params = [];

        foreach ($values as $id => $value) {
            $id = (int) $id;
            $cases[] = "WHEN {$id} then ?";
            $params[] = $value;
            $ids[] = $id;
        }

        $ids = implode(',', $ids);
        $cases = implode(' ', $cases);
        $params[] = Carbon::now();

        return \DB::update("UPDATE `{$table}` SET `value` = CASE `id` {$cases} END, `updated_at` = ? WHERE `id` in ({$ids})", $params);
    }

这显然将性能提高了 13 倍

2) 根据另一条评论,另一个想法是在每条记录的基础上执行此操作,但将整个事情作为单个事务执行,这样会更快。

    DB::beginTransaction();

    // your loop and updates;

    if( !$user )
    {
    rollbackTransaction();
    } else {
    // Else commit the queries
    commitTransaction();
    }


3) 还有一个 laravel 库似乎也试图解决这个问题。 https://github.com/mavinoo/laravelBatch

注意:我没有尝试或测试过上述任何解决方案。

【讨论】:

    【解决方案3】:

    我认为在没有 n 个查询的情况下这样做的唯一方法是

    • (可选)备份表
    • 获取记录并创建一个包含所有更新数据的数组
    • 批量删除记录
    • 从数组中批量插入

    这是 3 个查询。

    遍历 n 条记录对我的应用程序也不实用;我希望有一个替代方案,但看起来我将不得不实现它。

    【讨论】:

      【解决方案4】:

      请尝试以下代码:

      $data_to_be_updated = [ ['id'=>5,'name' => 'tarun'], ['id'=>6, 'name' => 'Akash'],
                              ['id'=>8, 'name' => 'Soniya'], ['id'=>9,'name' => 'Shalu']
                            ];
      foreach ($data_to_be_updated as $key => $value) {
          $data = Model::where('id',$value['id'])->first();
          if ($data) {
              $data->name = $value['name'];
              $data->save();
          }
      }
      

      【讨论】:

      • 在上面的示例中,将执行 8 个查询(4 个查询用于获取记录,4 个用于保存更新数据)。但我只想运行 1 个查询。
      • 不是批量查询
      【解决方案5】:

      你可以像上面提到的那样做:-

      foreach($ids as $key => $id) {
          Model::where('id', $id)->update($updated_array[$key]);
      }
      

      【讨论】:

        猜你喜欢
        • 2021-12-13
        • 1970-01-01
        • 2014-08-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-11-25
        • 1970-01-01
        相关资源
        最近更新 更多