【问题标题】:Rails ActiveRecord: Getting the id of a raw insertRails ActiveRecord:获取原始插入的 id
【发布时间】:2012-06-13 23:26:24
【问题描述】:
sql = DmozCategory.send(:sanitize_sql_array, ["INSERT INTO dmoz_categories (id, dmoz_category_title, dmoz_category_name, dmoz_category_description, created_at, updated_at, dmoz_category_lastupdate) VALUES (?, ?, ?, ?, NOW(), NOW(), ?)", result['catid'], result['title'], result['name'], result['description'], result['lastupdate']])

res = DmozCategory.connection.execute(sql)
$stderr.puts res.inspect

res 始终是nil,即使我可以看到 DmozCategory 插入到数据库中。如何在我的插入后获得id

我意识到我可以使用另一个 SQL 查询 SELECT LAST_INSERT_ID() 来获取 ID,但我想知道是否有办法通过 Rails 获取 ID。 M

背景:使用 Rails 2.3.14

更新:嗯,我认为问题出在我使用的名为 Octopus 的插件上。抱歉打折了您的一些答案。看来我需要找到如何使用此插件获取插入的最后一个 id。我完整的 coe:

desc "load all categories from dmoz" # With this one we're loading all the 'structure' table in, not the parent-child relationships.
  task :load_categories_from_dmoz, [ :offset, :limit ] => :environment do |t, args|
    offset = !args[:offset].blank? ? args[:offset].to_i : 0 # Take offset from args.  Default of 0
    limit = !args[:limit].blank? ? args[:limit].to_i : 1 # Take limit from args.  Default of 1
    ActiveRecord::Base.octopus_establish_connection(:adapter=> "mysql", :host=> "localhost", :database => "dmoz", :username => "dmoz", :password => "dmoz")

    results = ActiveRecord::Base.connection.select_all("SELECT * FROM structure LIMIT #{ offset }, #{ limit }") # Fetches it directly from the dmoz database.
    count = offset
    conn = ActiveRecord::Base.octopus_establish_connection(:adapter=> "mysql", :host=> "localhost", :database => "talon_development", :username => "rails_shadow", :password => "husky")
    results.each do |result|
      if count % 1000 == 0
        puts count
      end
      count +=1

      begin
        sql = DmozCategory.send(:sanitize_sql_array, ["INSERT INTO dmoz_categories (id, dmoz_category_title, dmoz_category_name, dmoz_category_description, created_at, updated_at, dmoz_category_lastupdate) VALUES (?, ?, ?, ?, NOW(), NOW(), ?)", result['catid'], result['title'], result['name'], result['description'], result['lastupdate']]) #We leave parent_id NULL for the next task to handle relationships

        DmozCategory.connection.execute(sql) #doesn't get the ID..

      end
    end
  end

【问题讨论】:

  • 试试exec_querylast_inserted_id(res)
  • @YuriBarbashov 我认为 Rails 2.3.14 中没有这种功能?
  • 你不是自己插入id吗? INSERT INTO dmoz_categories (id, ...) VALUES (?, ...), result['catid'], ...?
  • 是的,但我想稍后检查它是否有效。不确定是不是。

标签: sql ruby-on-rails activerecord octopus


【解决方案1】:

一般不要使用connection.execute,而是使用connection.insert

这将返回最后插入行的生成 id。它如何做到这一点取决于数据库。在 MySQL 上,最后一个插入 id 是连接的属性。在 Postgres 上,一个“返回”子句被附加到查询中(对于旧版本的 postgres,回退会询问序列的最后一个 id)。

使用 insert 而不是 execute 也会清除 rails 查询缓存。

至少在 MySQL 上,这将工作 even if you set the id yourself

【讨论】:

  • 我怎样才能得到身份证? DmozCategory.connection.idDmozCategory.connection.last_id 似乎没有我要插入的 id
  • connection.insert "INSERT ..." 应该返回 id(假设你的 id 是一个常规的自增列)
  • 哦,所以我不需要先使用.send?它同时发送和执行吗?
  • 查看.send的问题,它只是获取SQL。 DmozCategory.connection.insert(sql) 返回 0DmozCategory.connection.id 返回 2223123080,尽管我可以看到它已被插入到 ID 为 2 的表中。
  • 如果你碰巧在 PostgreSQL 上使用了外部数据包装器,那么调用#insert 将不会自动使用RETURNING;但是,您可以添加在远程服务器上运行的 INSERT 命令,它将返回远程 ID。有关INSERT ... RETURNING 的示例,请参见the docs
【解决方案2】:

我认为insert_sql 方法应该可以帮到你

DmozCategory.connection.insert_sql(sql) # => id

【讨论】:

    【解决方案3】:

    试试这个,这就是 AR 在 2.3 中插入​​之前定义 id 的方式

    id = DmozCategory.connection.next_sequence_value(DmozCategory.sequence_name)

    【讨论】:

    • undefined method next_sequence_value' for #<:connectionadapters::mysqladapter:0x10d1de1e8>`
    【解决方案4】:

    如果这是 mysql2 gem,并且DmozCategory.connection 是客户端的一个实例,DmozCategory.connection.last_id 将起作用。

    【讨论】:

    • 我使用mysql,所以undefined method last_id' 用于#<:connectionadapters::mysqladapter:0x106d82d48>`
    【解决方案5】:

    既然你已经知道id,你就不能这样做吗?

    dmoz_category = DmozCategory.find(result['id'])
    $stderr.puts dmoz_category.inspect
    

    【讨论】:

    • 开始看起来这是唯一的方法。不知道为什么,但其他一切都返回 0 或一个巨大/错误的数字
    【解决方案6】:

    假设您使用的是 MYSQL 并且表自动递增,您可以使用:

    SELECT LAST_INSERT_ID()
    

    按照它所说的,将最后插入的 ID 抓取到表中。这会在您的代码中添加另一个查询,但它似乎坚持使用原始 SQL。

    【讨论】:

    • 如果可能的话,我会更喜欢这种方式。这是唯一的方法吗?
    • 你可以这样做:DmozCategory.find(:last).id
    • 我不确定这是否可能,抱歉。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-11-25
    • 2021-11-04
    • 1970-01-01
    • 1970-01-01
    • 2011-02-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多