如何使用Laravel Eloquent实现数据库记录的更新或新增(不存在则创建)
解决Laravel Eloquent「有则更新,无则创建」的需求
嘿,刚接触Eloquent的话,你这个需求其实用Laravel内置的两个方法就能轻松搞定——updateOrCreate或者upsert,完美适配这种「目标记录存在就更新,不存在就新增」的场景~
方法一:用updateOrCreate替换原有update语句
这个方法最贴合你现有代码结构,直接把每一行的update换成updateOrCreate就行,逻辑清晰易懂:
// 处理ctv类型的记录 AccountID::updateOrCreate( // 第一个参数:查询条件,用来判断记录是否存在 ['account_id' => $account_id, 'screen_type' => 'ctv'], // 第二个参数:要更新/创建的字段数据 $update_account_ctv ); // 处理app类型的记录 AccountID::updateOrCreate( ['account_id' => $account_id, 'screen_type' => 'app'], $update_account_app ); // 处理site类型的记录 AccountID::updateOrCreate( ['account_id' => $account_id, 'screen_type' => 'site'], $update_account_site );
原理说明
updateOrCreate会先根据第一个数组的条件查询数据库:
- 如果找到匹配的记录,就用第二个数组的内容更新它;
- 如果没找到,就把两个数组的字段合并,创建一条新记录。
这个方法不需要额外操作数据库索引,直接就能用,非常适合你这种分类型单独处理的场景。
方法二:用upsert批量处理(更高效)
如果你想一次性完成三个类型的操作,可以用upsert方法,它能批量处理「更新或创建」,减少数据库查询次数,效率更高:
// 先把三个类型的记录整理成一个数组 $records = [ // 合并查询条件和要更新的数据 array_merge(['account_id' => $account_id, 'screen_type' => 'ctv'], $update_account_ctv), array_merge(['account_id' => $account_id, 'screen_type' => 'app'], $update_account_app), array_merge(['account_id' => $account_id, 'screen_type' => 'site'], $update_account_site), ]; // 执行批量upsert AccountID::upsert( $records, // 第一个参数:用来判断记录唯一性的字段(必须是数据库里的唯一索引) ['account_id', 'screen_type'], // 第二个参数:需要更新的字段(如果留空,默认更新所有非唯一性字段) array_keys($update_account_ctv) // 假设三个update数组的字段一致,不一致的话可以合并所有键 );
注意事项
用upsert的话,必须在你的account_id数据表上给account_id和screen_type这两个字段建立联合唯一索引,不然Laravel无法判断是否存在冲突记录,会直接抛出错误。
你可以通过迁移文件添加索引:
Schema::table('account_id', function (Blueprint $table) { $table->unique(['account_id', 'screen_type']); });
内容的提问来源于stack exchange,提问作者Bastian
相关产品推荐
相关产品推荐

