【问题标题】:fetch mysql prepared statement as array of hashes获取 mysql 准备好的语句作为哈希数组
【发布时间】:2013-06-09 14:54:21
【问题描述】:

我正在努力使用 ruby​​ 的 mysql gem 并准备语句。
我想以与 each_hash 相同的结果结束结果,但在准备语句中也不支持它。 所以我带着这个可怕的烂摊子来了。

  stmt = @db.prepare("SELECT mat_id, name, qty FROM materials WHERE mat_id = ? ")

  #those 3 lines hurt my eyes
  res = stmt.execute(params[:id])
  mat_id, name, qty  =  res.bind_result(Integer, String, Integer).fetch
  @material = [mat_id: mat_id, name: name, qty: qty]

必须有更好的方法来获取结果并获取哈希数组。

更好的 mysql gem 可能是一个有效的答案。 ORM 不是。

【问题讨论】:

  • 你试过mysql2 gem吗?
  • 一个 ORM 可能不是一个有效的答案,但您仍然应该查看 Sequel gem。它是我所知道的唯一一个让 SQL 爱好者感到自在的 ORM。
  • 为什么 ORM 不是一个有效的答案?不是所有的都是一样的,虽然有些做得不好,但其他的像 Sequel,非常灵活和强大,可以显着减轻你的编程负担。查看您的代码,我可以看到它在哪里有帮助。 sequel.rubyforge.org/rdoc/files/doc/…
  • @SergioTulentsev mysql2 不支持准备好的语句
  • @TheDisintegrator:Sequel 与其说是一种 ORM,不如说是一种操作抽象语法树的工具。基本上,它允许您使用 ruby​​ 操作 SQL 语法,并在您发出 fetch、insert 等时生成您想要的查询。您提到的 ORM 部分与该功能完全正交。将 Sequel 视为更高级且更红的 SQL gem,您将看到曙光。这是一款了不起的软件,我不知道其他语言中的任何等效软件。

标签: mysql ruby arrays hash prepared-statement


【解决方案1】:

看到cmets,我还是贴Sequel链接作为答案:

http://sequel.rubyforge.org/

您根本不需要使用 Sequel 的模型部分。事实上,文档有一整节专门介绍 SQL 爱好者:

http://sequel.rubyforge.org/rdoc/files/doc/sql_rdoc.html

示例查询:

DB.fetch("SELECT * FROM albums WHERE name LIKE ?", 'A%') do |row|
  puts row[:name]
end

【讨论】:

  • 好吧,你赢了。现在用续集。仍然为找不到更好的方式来表达问题的三个代码行而苦恼。
【解决方案2】:

Oneliner!

Hash[stmt.result_metadata.fetch_fields.map(&:name).zip( stmt.fetch )]

或者更强大

row = stmt.fetch
Hash[stmt.result_metadata.fetch_fields.map(&:name).zip( row )] if row

【讨论】:

    【解决方案3】:

    根据http://tmtm.org/en/mysql/ruby/,结果有一个“each_hash”方法,但语句没有。真是头疼啊……

    #A proxy for the statement class
    class Stmt
    
      def each_hash
        fields = @target.result_metadata.fetch_fields.map do |f| f.name.to_sym end 
        @target.execute.each do |x| 
          hash = {}
          fields.zip(x).each do |pair|
            hash[pair[0]] = pair[1]
          end 
          yield hash
        end 
      end 
    
      def initialize(target)
        @target = target
      end 
    
      def method_missing(name, *args, &block)
        @target.send(name, *args, &block)
      end 
    end
    

    现在,你可以这样做了:

    Stmt.new(@db.prepare(...).execute(...)).each_hash do |x|
      puts x
    end
    

    您可以将每一行作为哈希循环。

    我还没有测试过多次执行

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-09-16
      • 2012-08-05
      • 1970-01-01
      • 1970-01-01
      • 2019-05-26
      相关资源
      最近更新 更多