Как реализовать объемную вставку в Rails 3
Мне нужно вставить массив писем в разные записи в таблицу контактов. Как это можно сделать.
Eg: @email = ["[email protected]", "[email protected]", "[email protected]", ... ]
Я не хочу использовать.
@email.each do |email|
@contact = Contact.new
@contact.email = email
@contact.save
end
Эта причина n вставляет запросы. Мне просто нужен один запрос на вставку, чтобы вставить эти значения. Как это можно сделать в rails 3.0.9 (и в идеале MySQL). Пожалуйста, помогите
Ответы
Ответ 1
activerecord-import реализует импорт AR #
activerecord-import - это библиотека для массовой вставки данных с использованием ActiveRecord.
посмотреть, как это работает:
books = []
10.times do |i|
books << Book.new(:name => "book #{i}")
end
Book.import books
Дом проекта находится на Github и wiki.
Ответ 2
Вы также можете попробовать 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", поэтому вам не нужно проверять, существует ли запись. В вашем примере это не проблема, но в большинстве приложений она становится в конечном итоге.
Ответ 3
Простейшим способом без дополнительного gem является конкатция строки и ее выполнение в одной вставке 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)
Ответ 4
Я только что написал небольшую палитру обезьян для Active Record 3.2, чтобы вставить несколько новых записей с одним SQL-запросом, проверьте:
https://github.com/alexdowad/showcase/blob/master/activerecord/bulk_db_operations.rb