如何在Rails 3中实现批量插入

时间:2011-12-14 13:25:17

标签: ruby-on-rails ruby-on-rails-3 activerecord arel

我需要将一组电子邮件作为不同的记录插入到我的联系人表中。怎么办呢。

Eg: @email = ["a@b.com", "c@d.com", "e@f.com", ... ]

我不想使用。

  @email.each do |email|
     @contact = Contact.new
     @contact.email = email
     @contact.save
  end

这导致n插入quires。我只需要一个插入查询来插入这些值。如何在rails 3.0.9(以及理想的MySQL)中完成。请帮忙

4 个答案:

答案 0 :(得分:49)

activerecord-import 实现AR#import

activerecord-import是一个使用ActiveRecord批量插入数据的库。

了解它的工作原理:

books = []
10.times do |i| 
  books << Book.new(:name => "book #{i}")
end
Book.import books

项目的主页位于Github,而wiki

答案 1 :(得分:4)

您也可以尝试upsert,这与activerecord-import差不多,但只适用于(当前)MySQL,Postgres和SQLite3:

require 'upsert'
Upsert.batch(Contact.connection, Contact.table_name) do |upsert|
  emails.each do |email|
    upsert.row(email: email)
  end
end

请注意,这涉及每个记录一个数据库查询,但它是一个“upsert”,因此您不必检查记录是否已存在。在您的示例中,这不是问题,但在大多数应用程序中,它最终成为一个。

答案 2 :(得分:2)

没有额外gem的最简单方法是连接一个字符串并在一次SQL插入(http://www.electrictoolbox.com/mysql-insert-multiple-records/)中执行它。

@email = ["a@b.com", "c@d.com", "e@f.com"]

time = Time.current.to_s(:db)

values = @email.map do |email|
  "('#{email}', '#{time}', '#{time}')"
end

sql = "INSERT INTO contacts (email, created_at, updated_at) VALUES #{values.join(', ')}"
Contact.connection.execute(sql)

答案 3 :(得分:1)

我刚刚为Active Record 3.2编写了一个小小的补丁,用一个SQL查询插入许多新记录,检查出来:

https://github.com/alexdowad/showcase/blob/master/activerecord/bulk_db_operations.rb