批量插入更新upsert

如果问我一批数据根据指定字段插入或者更新,我第一反应是循环去updateOrCreate, 事实上从Laravel8开始这一切变得非常优雅。

updateOrCreate有个非常糟糕的点就是先去查找,没有找到然后在去插入数据,找到了然后去更新,这样效率是很低的。

假设我有一批数据

$data = [
  ['goods_id' => 1,'title' => '电动牙刷'],
  ['goods_id' => 2,'title' => '情趣内衣'],
  ['goods_id' => 3,'title' => 'Iphone12']
]

// example updateOrCreate
foreach($data as $item) {
  Product::query()->updateOrCreate(
    ['goods_id' => $item['goods_id']], $item
  );
}

// example upsert
Product::query()->upsert($data, ['goods_id'])

upsert方法的第一个参数是由要插入或更新的值组成,而第二个参数列出相应表中惟一标识记录的列,该方法的第三个也是最后一个参数是一个列数组,即如果数据库中已经存在匹配的记录,应该被更新的列。如果模型上启用了时间戳,upsert 方法将自动设置 created_atupdated_at 时间戳

结语

有兴趣的同学可以测试一下,特别是在数据多点的情况下upsert效率那是高的不是一点点

听说有图会有人点赞

本作品采用《CC 协议》,转载必须注明作者和本文链接
《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
《G01 Go 实战入门》
从零开始带你一步步开发一个 Go 博客项目,让你在最短的时间内学会使用 Go 进行编码。项目结构很大程度上参考了 Laravel。
讨论数量: 26

谢谢。谢了

2年前 评论
半人间 2年前

//试了 这样可以批量写入
Tests::upsert([['name'=>'flowerhua','age'=>10],['name'=>'flowerhua2','age'=>20]],['id']);

$data = [
    ['id'=>1,'name'=>'flowerhua','age'=>10],['name'=>'flowerhua2','age'=>20]
];

//例如商品新增了一个规格,修改了一个规格 我的数据是一条写入 一条修改如何操作呢?
2年前 评论
luyang (楼主) 2年前
flowerhua (作者) 2年前
luyang (楼主) 2年前

看这个提示,怎么感觉 upsert 跟数据库的 INSERT INTO xxx ON DUPLICATE KEY UPDATE 一样呢。。这种操作特别费自增主键。。

除 SQL Server 之外的所有数据库都要求 upsert 方法的第二个参数中的列具有 “primary” 或 “unique” 索引。

2年前 评论
SuperLeo 1年前
SuperLeo 2年前
WhiteDragon (作者) 2年前
tiantian10000 1年前
tiantian10000 1年前
SuperLeo 1年前
tiantian10000 1年前
SuperLeo 1年前
SuperLeo 1年前
tiantian10000 1年前
tiantian10000 1年前
tiantian10000 1年前
tiantian10000 1年前
tiantian10000 1年前
SuperLeo 1年前
tiantian10000 1年前

@白小白 本身就是为了唯一性来做处理的,不用主键也可以,只要是唯一组合就行

2年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!