Laravel 10.43新增insertIgnoreUsing方法的价值及批量插入用法问询
Laravel 10.43
insertIgnoreUsing 方法详解与使用指南 方法核心作用
insertIgnoreUsing 是Laravel 10.43新增的查询构建器方法,专门用于基于数据库查询结果批量插入数据,同时自动忽略因唯一约束等冲突导致的插入失败。
和旧版insertIgnore的区别:
- 旧版
insertIgnore需要手动构造要插入的数组数据,适合已知固定数据集的批量插入 - 新版
insertIgnoreUsing则直接以另一个数据库查询的结果作为数据源,适合跨表同步、筛选后批量导入这类依赖现有数据的场景
基础用法拆解
官方示例的逻辑非常清晰,我们来拆解它的执行流程:
示例代码
$result = $builder->from('table1')->insertOrIgnoreUsing( ['foo'], // 目标表`table1`要插入的字段 function (Builder $query) { // 定义数据源查询:从`table2`筛选符合条件的`bar`字段 $query->select(['bar'])->from('table2')->where('foreign_id', '=', 5); } );
对应生成的SQL
INSERT IGNORE INTO `table1` (`foo`) SELECT `bar` FROM `table2` WHERE `foreign_id` = ?
参数说明
- 第一个参数:目标表需要插入的字段名数组,必须和数据源查询返回的字段顺序/数量匹配
- 第二个参数:可以是闭包(接收
Builder实例),也可以直接传入已构建好的Builder查询对象,用来定义提供数据的查询语句
批量插入的实际场景示例
以下是贴近实际开发的场景,帮助你理解如何用它实现批量插入:
场景:同步用户邮箱到备份表(忽略已存在的邮箱)
假设我们有users表和email_backups表,需要把所有未备份的用户邮箱批量导入备份表,同时忽略已经存在的邮箱(依赖email字段的唯一约束):
use Illuminate\Database\Query\Builder; use Illuminate\Support\Facades\DB; // 执行批量插入 $affectedRows = DB::table('email_backups')->insertIgnoreUsing( ['email', 'user_id'], // 备份表的字段 function (Builder $query) { // 从users表筛选未备份的用户数据 $query->select(['email', 'id']) ->from('users') ->whereNotExists(function ($subQuery) { $subQuery->select(DB::raw(1)) ->from('email_backups') ->whereColumn('email_backups.email', 'users.email'); }); } ); // $affectedRows 返回成功插入的行数(冲突记录不计入)
场景:批量插入统计结果
从订单表统计每个用户的订单数,插入到用户统计表里,忽略已存在的用户统计记录:
$affectedRows = DB::table('user_order_stats')->insertIgnoreUsing( ['user_id', 'order_count'], function (Builder $query) { $query->select(['user_id', DB::raw('COUNT(*) as order_count')]) ->from('orders') ->groupBy('user_id'); } );
关键注意事项
- 依赖数据库语法:该方法本质生成
INSERT IGNORE ... SELECT ...语句,MySQL/MariaDB原生支持;PostgreSQL会自动适配为ON CONFLICT DO NOTHING - 字段匹配:目标表字段和查询返回的字段必须数量一致、类型兼容,否则会插入失败
- 返回值:仅统计成功插入的行数,因冲突被忽略的记录不计入
内容的提问来源于stack exchange,提问作者MartinTTS
相关产品推荐
相关产品推荐

