在Laravel的大规模upsert(雄辩)

nx7onnlm  于 2023-01-31  发布在  其他
关注(0)|答案(4)|浏览(266)

是否有办法在Laravel(MySQL数据库)中批量插入(插入或更新,如果存在)记录?
假设我有一张table,上面有:

[id:1 value:4]
[id:2 value:5]

我想执行:

Model::massupsert([
  [id:1 value:100],
  [id:3 value:20]
]);

之后的表为:

[id:1 value:100]
[id:2 value:5]
[id:3 value:20]
q9yhzks0

q9yhzks01#

现在(2020年10月6日),Laravel(v8.10.0)拥有原生upsert支持。https://github.com/laravel/framework/pull/34698

Model::upsert([
    ['id' => 1, 'value' => 100],
    ['id' => 3, 'value' => 20],
], 'id');
3bygqnnd

3bygqnnd2#

Laravel没有原生UPSERT支持。
我已经为此创建了一个包:https://github.com/staudenmeir/laravel-upsert

Model::upsert([
    ['id' => 1, 'value' => 100],
    ['id' => 3, 'value' => 20],
], 'id', ['value']);
wecizke3

wecizke33#

当然,你可以使用updateOrCreate()方法。引用文档:
你也可能遇到这样的情况,你想要更新一个现有的模型或者创建一个新的模型,Laravel提供了一个updateOrCreate方法来一步完成。

$data = collect([
    ['id' => 1, 'value' => 100],
    ['id' => 3, 'value' => 20]
]);

$data->each(function ($item) {
    Model::updateOrCreate([
        ['id' => $item['id']],
        ['value' => $item['value']]
    ]);
});

**注意:**如果您必须一次处理许多记录,则此方法可能会导致处理速度变慢,因为您一次只能在数据库中创建/更新一个模型。

更新#1:减少质询

然后,您可以使用firstOrNew稍微减少查询次数,因为您只是将新记录批量插入到数据库中,但目前您必须手动更新已经存在的记录,一次更新一条记录:

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

目前,要使用单个查询完成此操作,您必须使用 Jonas Staudenmeir 在评论中建议的包。

siv3szwd

siv3szwd4#

Laravel 8现在有一个upsert功能,我在上一个项目中使用过。我非常喜欢它!
https://laravel.com/docs/8.x/queries#update-statements
upsert方法将插入不存在的记录,并用您指定的新值更新已存在的记录。该方法的第一个参数由要插入或更新的值组成。而第二个参数列出列唯一标识关联表中记录的方法。方法'的第三个也是最后一个参数是一个列数组,如果数据库中已存在匹配记录,则应更新该数组:

DB::table('flights')->upsert([
    ['departure' => 'Oakland', 'destination' => 'San Diego', 'price' => 99],
    ['departure' => 'Chicago', 'destination' => 'New York', 'price' => 150]
], ['departure', 'destination'], ['price']);

相关问题