如何使用Rails ActiveRecord一次运行两个数据库命令?

时间:2014-10-11 20:39:31

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

我试图直接加载到Rails中的PostgreSQL表。我的连接建立如下:

  rc = connection.raw_connection
  rc.exec("COPY research FROM STDIN WITH CSV HEADER")

以下是代码的一部分:

    for key,values in valuehash
      entry = standard.model_constant::ATTRIBUTE_HASH[key.to_sym]
      puts "Loading #{entry[:display]}..."
      values.each do |value|
        id = ActiveRecord::Base.connection.execute("select nextval('research_id_seq'::regclass)").first['nextval']

        line = [id, value, entry[:display], standard.id, now, now]
        until rc.put_copy_data( line.to_csv )
          ErrorPrinter.print "  waiting for connection to be writable..."
          sleep 0.1
        end
      end
    end

开始id =的行失败。它说:

ActiveRecord::StatementInvalid: PG::UnableToSend: another command is already in progress

我不想将所有这些值写入CSV文件,然后读入该文件。我只想将内存中的数据发送到数据库。我无法想出为什么我不能在同一个表上运行同一个数据库的两个连接的正当理由,所以我认为我必须做错事。我尝试了两个原始连接,但它始终从池中给我相同的连接。

1 个答案:

答案 0 :(得分:1)

处理此问题的最佳方法是让数据库为您插入序列号,而不是尝试获取和添加它们。

假设您的表定义如下:

CREATE TABLE research (
    id SERIAL,
    value TEXT, 
    ...
)

然后定义表,如果插入一行,并且没有为id指定值,则它将自动默认为序列中的值。这同样适用于COPY和任何其他形式的插入行。

诀窍是确保您没有提供价值。为此,请构造COPY命令,以便不包含id列:

COPY research(value,....) FROM STDIN WITH CSV HEADER

即。您必须指定要为其提供数据的字段列表,以及您提供数据的顺序。

请注意,即使您有标题,也不会在导入时使用它来确定存在的列或其顺序。标题刚刚丢弃。

假设您更改了COPY语句,那么您只需从正在构建的值数组中删除id以发送到数据库。