I have a project written using PHP on the top of Laravel 5.7. I am using Eloquent ORM to interact with the database.
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. If the size of $values
array is 1000. That's going to generate up to 2000 queries which are insane!
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:
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.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.