Existe-t-il un moyen d'upsert en masse (insérer ou mettre à jour s'il existe) des enregistrements dans Laravel (base de données MySQL)?
Disons que j'ai une table avec:
[id:1 value:100] [id:2 value:5] [id:3 value:20]
Je veux jouer:
Model::massupsert([ [id:1 value:100], [id:3 value:20] ]);
Et la table après être:
[id:1 value:4] [id:2 value:5]
3 Réponses :
Bien sûr, vous pouvez utiliser la méthode updateOrCreate()
. Citant la documentation :
Vous pouvez également rencontrer des situations dans lesquelles vous souhaitez mettre à jour un modèle existant ou créer un nouveau modèle s'il n'en existe pas. Laravel fournit une méthode updateOrCreate pour ce faire en une seule étape.
$data = collect([ ['id' => 1, 'value' => 100], ['id' => 3, 'value' => 20] ]); $models = $data->map(function ($attributes) { $model = Model::firstOrCreate([ ['id' => $attributes['id']], ['value' => $attributes['value']] ]); if (! $model->exists) { $model->fill($attributes); } return $model; }); list($saved, $unsaved) = $models->partition(function ($model) { return $model->exists; }); Model::insert($unsaved); $saved->each->update();
Remarque: si vous devez traiter plusieurs enregistrements à la fois, cette méthode peut ralentir le traitement, car vous créez / mettez à jour un modèle à la fois dans la base de données.
Vous pouvez alors réduire un peu le nombre de requêtes avec firstOrNew
, car vous insérez simplement en bloc les nouveaux enregistrements dans la base de données, mais vous devez actuellement mettre à jour manuellement les enregistrements déjà existants un par un:
$data = collect([ ['id' => 1, 'value' => 100], ['id' => 3, 'value' => 20] ]); $data->each(function ($item) { Model::updateOrCreate([ ['id' => $item['id']], ['value' => $item['value']] ]); });
Actuellement, pour faire cela avec une seule requête, vous devez utiliser un package comme suggéré par Jonas Staudenmeir dans les commentaires.
Merci mais je recherche une solution qui se traduit par 1 requête SQL et non par plusieurs appels (pour de meilleures performances)
@Yaron Avez-vous trouvé une meilleure solution pour réduire la taille de la requête?
Laravel n'a pas de support natif d'UPSERT.
J'ai créé un package pour cela: https://github.com/staudenmeir/laravel-upsert
Model::upsert([ ['id' => 1, 'value' => 100], ['id' => 3, 'value' => 20], ], 'id', ['value']);
Maintenant, Laravel a upsert
support natif d' upsert
. https://github.com/laravel/framework/pull/34698
Model::upsert([ ['id' => 1, 'value' => 100], ['id' => 3, 'value' => 20], ], 'id');
Quelle base de données utilisez-vous?
J'utilise la base de données mysql.
Laravel n'a pas (encore) de support natif d'upsert. Vous pouvez utiliser ce package: github.com/yadakhov/insert-on-duplicate-key
Merci, c'est ce que je cherchais.
Si vous le mettez comme réponse, je le marquerai comme la solution.