简体   繁体   English

如何使用Laravel和Eloquent更新多个记录?

[英]How to updated multiple records with Laravel and Eloquent?

I have a project written using PHP on the top of Laravel 5.7. 我在Laravel 5.7的顶部有一个使用PHP编写的项目。 I am using Eloquent ORM to interact with the database. 我正在使用Eloquent ORM与数据库进行交互。

I need to be able to update lots of records after pulling them from the database. 从数据库中提取很多记录后,我需要能够更新很多记录。

Here is how I am trying to do it. 这就是我正在尝试做的事情。

$records = Record::where('Key','Test')->get();

$values = collecT([
  ['Id' => 1, 'Col' => 100],
  ['Id' => 2, 'Col' => 200],
  ['Id' => 3, 'Col' => 500],
  ....
]);

foreach($records as $record) {
  $newValue = $values->where('Id', $record->id)->first();

  if(is_null($newValue)){
      continue;
  }

  $record->ColName = $newValue['Col'];
  $record->save();
}

The above code does not write the updated value to the database. 上面的代码未将更新后的值写入数据库。 However, if I do the following it gets updated 但是,如果我执行以下操作,它将更新

foreach($values as $value) {
    $record = Record::where('Key','Test')->where('id', $value['Id'])->first();

    if(is_null($record)){
       continue;
    }

    $record->ColName = $value['Col'];
    $record->save();
}

Although the above code works, I have to make 1 select + 1 update statement for every record in the $values array. 尽管上面的代码有效,但我必须为$values数组中的每条记录做出1 select + 1 update语句。 If the size of $values array is 1000. That's going to generate up to 2000 queries which are insane! 如果$values数组的大小为1000。这将生成多达2000个疯狂的查询!

How can I correctly update multiple records in the database without doing range-update. 如何在不进行范围更新的情况下正确更新数据库中的多个记录。

If all the rows you are trying to update would get the same value it is an easy problem. 如果您尝试更新的所有行都将获得相同的值,这是一个简单的问题。 The problem becomes a bit more tricky because all your rows need to be updated with different values. 这个问题变得更加棘手,因为所有行都需要使用不同的值进行更新。 This comment on a github issue of laravel has a solution that will do it with a single query, allowing him in that case with a 13x performance boost for 1000 rows to be updated compared to updating them one by one: 这篇关于laravel的github问题的评论提供了一个解决方案,该解决方案可以通过单个查询来实现,在这种情况下,与一遍一遍地更新相比,他可以对1000行进行13倍的性能提升:

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);
}

You can also try https://github.com/mavinoo/laravelBatch which does something similar. 您也可以尝试执行类似操作的https://github.com/mavinoo/laravelBatch

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM