Как обновить несколько записей с помощью Laravel и Eloquent? - PullRequest
0 голосов
/ 17 января 2019

У меня есть проект, написанный с использованием PHP на вершине Laravel 5.7. Я использую Eloquent ORM для взаимодействия с базой данных.

Мне нужно иметь возможность обновлять много записей после извлечения их из базы данных.

Вот как я пытаюсь это сделать.

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

Приведенный выше код не записывает обновленное значение в базу данных. Однако, если я сделаю следующее, он будет обновлен

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

Хотя приведенный выше код работает, мне нужно сделать 1 оператор выбора + 1 для каждой записи в массиве $values. Если размер массива $values равен 1000. Это сгенерирует до 2000 безумных запросов!

Как правильно обновить несколько записей в базе данных без обновления диапазона.

1 Ответ

0 голосов
/ 18 января 2019

Если все строки, которые вы пытаетесь обновить, получат одинаковое значение, это простая проблема. Проблема становится немного сложнее, потому что все ваши строки должны быть обновлены с различными значениями. Этот комментарий к проблеме GitHub для laravel предлагает решение, которое сделает это с помощью одного запроса, что позволит ему в 13 раз повысить производительность на 1000 строк по сравнению с обновлением их одна за другой:

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

Вы также можете попробовать https://github.com/mavinoo/laravelBatch, что делает нечто подобное.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...