批量插入更新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 协议》,转载必须注明作者和本文链接
《L05 电商实战》
从零开发一个电商项目,功能包括电商后台、商品 & SKU 管理、购物车、订单管理、支付宝支付、微信支付、订单退款流程、优惠券等
《L03 构架 API 服务器》
你将学到如 RESTFul 设计风格、PostMan 的使用、OAuth 流程,JWT 概念及使用 和 API 开发相关的进阶知识。
讨论数量: 26

谢谢。谢了

3年前 评论
半人间 3年前

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

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

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

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

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

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

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

3年前 评论

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