如何使用mysql2 gem创建预准备语句?

时间:2012-03-28 11:21:43

标签: mysql ruby ruby-on-rails-3 ruby-on-rails-3.1

我尝试使用谷歌来回答这个看似简单的问题,但令我惊讶的是,它没有帮助。

我的rails应用程序中的代码目前正在使用mysql gem的'prepare'方法。切换到mysql2时,会出现错误:

undefined method `prepare' for #<Mysql2::Client::0.......

所以我尝试寻找'prepare'方法的一个版本,但到目前为止这个搜索都没有成功。任何人都可以帮我解决这个问题吗?

编辑:如果这是不可能的,有人可以让我知道是否有办法简单地用mysql2库中的东西参数化我的查询?

7 个答案:

答案 0 :(得分:14)

<强>更新

正如Ryan Rapp指出的那样,mysql2现在支持预处理语句。以下代码段摘自readme

statement = @client.prepare("SELECT * FROM users WHERE login_count = ?")
result1 = statement.execute(1)
result2 = statement.execute(2)

statement = @client.prepare("SELECT * FROM users WHERE last_login >= ? AND location LIKE ?")
result = statement.execute(1, "CA")

谢谢Ryan!

原帖

我也没有找到这样的功能;既不在source也不在documentation。 也许下面的代码片段可以替代您的需求? (在mysql2 gem的文档中找到):

escaped = client.escape("gi'thu\"bbe\0r's")
results = client.query("SELECT * FROM users WHERE group='#{escaped}'")

答案 1 :(得分:6)

mysql2 gem现在支持根据documentation准备好的语句。

语法如下:

statement = @client.prepare("SELECT * FROM users WHERE login_count = ?")
result1 = statement.execute(1)
result2 = statement.execute(2)

这是added,2015年6月合并拉取请求。

答案 2 :(得分:3)

我换出使用https://github.com/tmtm/ruby-mysql而不是mysql2。令我惊讶的是,对于使用mysql2 gem的人来说,这不是一个更大的交易破坏者。我想那些深入研究SQL的人已经交换到Postgresql了?

如果其他人遇到问题gem install ruby-mysql后跟require "mysql",您会收到像'read_eof_packet': packet is not EOF (Mysql::ProtocolError)这样的红宝石错误,诀窍是gem uninstall ruby-mysql而不是gem install ruby-mysql-ext (或在你的Gemfile中使用gem 'ruby-mysql-ext',它将换掉Ruby实现,这个实现还不兼容Ruby 2.0(或者至少对我来说不起作用),用于简单的C绑定。

要明确的是,如果在安装require 'mysql'ruby-mysql-ext的同时执行ruby-mysql,它将加载Ruby版本。可能有一种方法需要在特定的宝石中,但我没有时间查找它。

答案 3 :(得分:1)

是的,mysql2适配器不支持绑定,直到当前的Rails 4.0。我很惊讶!您可以通过〜/ .rvm / gems / ruby​​-2.1.1 / gems / activerecord-4.1.1 / lib / active_record / connection_adapters / mysql2_adapter.rb中的代码片段来判断这一点

      def exec_query(sql, name = 'SQL', binds = [])
        result = execute(sql, name)
        ActiveRecord::Result.new(result.fields, result.to_a)
      end

      alias exec_without_stmt exec_query

      # Returns an ActiveRecord::Result instance.
      def select(sql, name = nil, binds = [])                                                                                                                      
        exec_query(sql, name)
      end

这也有助于您理解:

(在〜/ .rvm / gems / ruby​​-2.1.1 / gems / activerecord-4.1.1 / lib / active_record / connection_adapters / abstract / database_statements.rb)

      # Returns an ActiveRecord::Result instance.
      def select_all(arel, name = nil, binds = [])
        if arel.is_a?(Relation)
          relation = arel
          arel = relation.arel                                                                                                                                     
          if !binds || binds.empty?
            binds = relation.bind_values
          end
        end

        select(to_sql(arel, binds), name, binds)
      end

那就是它!我猜我可能会转向Postgres !!

答案 4 :(得分:0)

我还惊讶于缺少准备方法。当然,在一个常见的ActiveRecord和Mysql2设置中,ActiveRecord必须转义字符串,而不是使用libmysql,我觉得有点担心。

与此同时,您可以使用https://github.com/brianmario/mysql2/tree/stmt

答案 5 :(得分:0)

据我所知,Rails和MySQL Active Record适配器对预准备语句没有任何支持:

http://patshaughnessy.net/2011/10/22/show-some-love-for-prepared-statements-in-rails-3-1

这是因为它们实际上对加速语句没有任何用处,并且由于MySQL缺乏查询规划,实际上可能会减慢速度。

答案 6 :(得分:0)

您也可以使用mysql2-cs-bind gem: https://github.com/tagomoris/mysql2-cs-bind