web-dev-qa-db-ja.com

Rails 3で一括挿入を実装する方法

連絡先テーブルにさまざまなレコードとして一連の電子メールを挿入する必要があります。これはどのように行うことができますか。

Eg: @email = ["[email protected]", "[email protected]", "[email protected]", ... ]

使いたくない。

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

これにより、n個の挿入要求が発生します。これらの値を挿入するには、1つの挿入クエリが必要です。 Rails 3.0.9(そして理想的にはMySQL)でこれをどのように行うことができますか?助けてください

23
Amal Kumar S

activerecord-importはAR#importを実装します

activerecord-importは、ActiveRecordを使用してデータを一括挿入するためのライブラリです。

それがどのように機能するかを見てください:

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

プロジェクトのホームは Github にあり、 wiki です。

51
Anatoly

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

これには、レコードごとに1つのデータベースクエリが含まれますが、これは「アップサート」であるため、レコードがすでに存在するかどうかを確認する必要はありません。あなたの例では、これは問題ではありませんが、ほとんどのアプリケーションでは、最終的には1つになります。

4
Seamus Abshere

追加のgemを使用しない最も簡単な方法は、文字列を連結して1回のSQL挿入で実行することです( http://www.electrictoolbox.com/mysql-insert-multiple-records/ )。

@email = ["[email protected]", "[email protected]", "[email protected]"]

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)
2
nnattawat

単一のSQLクエリで多くの新しいレコードを挿入するためのActiveRecord3.2用の小さなモンキーパッチを作成しました。チェックしてください。

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

1
Alex D