如何批量插入Arel?

时间:2015-10-19 13:08:54

标签: ruby-on-rails ruby postgresql ruby-on-rails-4 arel

我有类似下面的循环,它创建了许多插入:

\d==\\d

但是,我想找到一种方法来只获取要插入的值。在这里我可以为所有值做一次插入。

PS:请注意我不想编写sql字符串(安全问题)。

table = Arel::Table.new(:users)
users.each do |user|
  manager = Arel::InsertManager.new(ActiveRecord::Base)
  manager.into(table).insert([
    [table[:name], user.name],
    [table[:created_at], user.created_at],
    [table[:updated_at], user.updated_at]
  ])
  # INSERT INTO users (name) VALUES ('a')
  @conn.insert(manager.to_sql)
end

4 个答案:

答案 0 :(得分:2)

本月早些时候有一个名为bulk_insert的图书馆。这应该为您提供您正在寻找的功能:

Model.bulk_insert do |worker|
  worker.add(...)
  worker.add(...)
  ...
end

# Produces:
INSERT INTO models (...) VALUES
  (...),
  (...),
  (...),
  (...),
  ...

由于这是一个相当新的图书馆,我没有机会玩它,我不确定它的Arel功能。

答案 1 :(得分:2)

您可以使用Active Record Import

答案 2 :(得分:0)

查看bulk_insert(感谢@Gavin Miller),我意识到他们使用Rails cote来阻止sql注入。

因为我需要定制的东西,所以我不会选择宝石。所以,我的最终解决方案是在其他人有类似要求的情况下:

inserts = []
users.each do |user|
  inserts << %{(
    #{@conn.quote(user.name)},
    #{@conn.quote(user.created_at)},
    #{@conn.quote(user.updated_at)}
  )}
end

sql = %{
  INSERT INTO users
  (name, created_at, updated_at)
  VALUES #{inserts.join(',')}
}

@conn.execute(sql)

答案 3 :(得分:0)

如果您的AREL版本已经支持create_tuple,它将是:

        table = Table.new(:users)
        manager = Arel::InsertManager.new
        manager.into table

        manager.columns << table[:id]
        manager.columns << table[:name]

        manager.values = manager.create_tuple([
          manager.create_values(%w{ 1 david }),
          manager.create_values(%w{ 2 kirs }),
          manager.create_values(["3", Arel.sql('DEFAULT')], []),
        ])

        # INSERT INTO "users" ("id", "name") VALUES ('1', 'david'), ('2', 'kirs'), ('3', DEFAULT)
      end

从这里拍摄:https://github.com/kirs/arel/blob/5d6d14cb6be217abc04253da0fe49721d09e9575/test/test_insert_manager.rb#L31