【问题标题】:How can I run two database commands at once with Rails ActiveRecord?如何使用 Rails ActiveRecord 一次运行两个数据库命令?
【发布时间】:2014-12-06 18:46:23
【问题描述】:

我正在尝试直接加载到 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 文件,然后读入该文件。我只想将数据从内存直接发送到数据库。我想不出为什么我不能针对同一个表运行到同一个数据库的两个连接的正当理由,所以我想我一定是做错了什么。我尝试了两个原始连接,但它总是给我来自池的相同连接。

【问题讨论】:

  • 您必须自己向序列询问 ID 似乎很奇怪。如果您插入一条记录但不包含 id 字段,则序列应自动填充它。
  • 对于 id 行,为什么不使用rc 连接来获取 id?或者,为什么不为表创建一个模型,以便可以使用标准 ActiveRecord 插入数据库?如果您担心速度,可以使用github.com/zdennis/activerecord-import
  • Don - 在直接插入时,您必须提供序列,没有自动增量。约翰,我先试过了。当你这样做时,它会终止 COPY 命令。不过,我会检查 activerecord-import,谢谢。

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


【解决方案1】:

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

假设您的表定义如下:

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

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

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

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

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

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

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

【讨论】:

    猜你喜欢
    • 2012-11-25
    • 2018-02-26
    • 1970-01-01
    • 1970-01-01
    • 2023-03-05
    • 2011-10-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多