You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Rails 5.2中如何用单语句批量创建关联记录?

Rails 5.2.6.2 批量创建父级及关联子记录提速方案

一、用 activerecord-import 实现关联批量插入

这个gem支持批量插入并返回生成的ID,刚好能解决父-子关联的批量创建问题,步骤如下:

  1. 安装gem:
# 在Gemfile中添加
gem 'activerecord-import'
# 执行bundle install
  1. 批量插入父记录并获取ID,再批量插入子记录:
# 构造父记录集合(跳过验证)
parent_records = (1..1000).map { |i| Parent.new(name: "Parent #{i}") }

# 批量插入父记录,指定returning: [:id]会自动填充实例的id属性
Parent.import parent_records, validate: false, returning: [:id]

# 构造子记录集合,关联父ID
child_records = []
parent_records.each_with_index do |parent, idx|
  5.times do |j|
    child_records << Child.new(
      parent_id: parent.id,
      content: "Child #{idx}-#{j}",
      created_at: Time.current,
      updated_at: Time.current
    )
  end
end

# 批量插入子记录
Child.import child_records, validate: false

二、自定义PostgreSQL SQL实现一次性批量插入

利用PostgreSQL的WITH子句和RETURNING语法,可以在单条SQL中完成父、子记录的批量插入,性能更优:

# 构造父记录的VALUES片段,注意用connection.quote做转义避免SQL注入
parent_values = (1..1000).map do |i|
  "(#{ActiveRecord::Base.connection.quote("Parent #{i}")}, NOW(), NOW())"
end.join(',')

# 构造完整SQL:先插入父记录,再用返回的ID插入子记录
sql = <<~SQL
  WITH inserted_parents AS (
    INSERT INTO parents (name, created_at, updated_at)
    VALUES #{parent_values}
    RETURNING id
  )
  INSERT INTO children (parent_id, content, created_at, updated_at)
  SELECT 
    ip.id, 
    'Child ' || ip.id || '-' || gs.num, 
    NOW(), 
    NOW()
  FROM inserted_parents ip
  CROSS JOIN generate_series(1,5) gs(num)
SQL

# 执行SQL
ActiveRecord::Base.connection.execute(sql)

注意事项

  • 两种方案都跳过了模型验证,符合需求;如果需要部分验证,可调整validate参数或手动处理
  • 批量插入时需手动设置created_at和updated_at(因为跳过了模型回调)
  • activerecord-import更贴合Rails开发习惯,维护成本低;自定义SQL性能略高,但需要手动处理字段和转义逻辑

内容的提问来源于stack exchange,提问作者C. Ball

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 07:05:07