10

我熟悉 Ruby on Rails、DB(MS) 驱动程序和存储过程之间长期存在的爱恨交织关系,我从 2.3.2 版开始就一直在开发 Rails 应用程序。

但是,每隔一段时间就会出现这样一种情况,即 SP 只是比在(慢得多的)应用程序级别上组合数据更好的选择。具体来说,运行结合了来自多个表的数据的报告通常更适合 SP。

为什么存储过程仍然如此糟糕地集成到 Rails 或 MySQL gem 中。我目前正在使用 Rails 3.0.10 和 MySQL2 gem 0.2.13 开发一个项目,但据我所知,即使是最新的 Edge Rails 和 MySQL gem 0.3+ 在使用 SP 时仍然会发脾气。

一直存在并且仍然存在的问题是调用 SP 后数据库连接丢失。

>> ActiveRecord::Base.connection.execute("CALL stored_proc")
=> #<Mysql::Result:0x103429c90>
>> ActiveRecord::Base.connection.execute("CALL stored_proc")
ActiveRecord::StatementInvalid: Mysql::Error: Commands out of sync; 
[...]
>> ActiveRecord::Base.connection.active?
=> false
>> ActiveRecord::Base.connection.reconnect!
=> nil
>> ActiveRecord::Base.connection.execute("CALL proc01")
=> #<Mysql::Result:0x1034102e0>
>> ActiveRecord::Base.connection.active?
=> false

从技术上讲,这是一个很难解决的问题,还是 Rails 的设计选择?

4

3 回答 3

10

rails 支持存储过程。您得到的不同步错误是因为MULTI_STATEMENTS在 Rails 中默认情况下未启用 MySQL 的标志。此标志允许过程返回超过 1 个结果集。

有关如何启用它的代码示例,请参见此处:https ://gist.github.com/wok/1367987

存储过程可与 MS SQL Server 一起使用。

我在几乎所有基于 mySQL 和 SQL Server 的 rails 项目中都使用了存储过程,但没有任何发布。

于 2013-02-25T09:17:06.953 回答
3

这是为了让 postgres 执行一个返回 MyClass 实例的存储过程。

sql=<<-SQL
select * from my_cool_sp_with_3_parameters(?, ?, ?) as 
foo(
  column_1 <type1>,
  column_2 <type2>
)
SQL

MyClass.find_by_sql([sql, param1, param2, param3]);

将 foo() 中的列列表替换为模型中的列和存储过程结果。我确信这可以通过检查类的列来通用。

于 2012-07-27T17:13:42.793 回答
0

那些遇到同步错误的人可能有产生多个结果的程序。你需要做这样的事情来处理它们:

raise 'You updated Rails. Check this duck punch is still valid' unless Rails.version == "3.2.15"
module ActiveRecord
  module ConnectionAdapters
    class Mysql2Adapter
      def call_stored_procedure(sql)
        results = []
        results << select_all(sql)
        while @connection.more_results?
          results << @connection.next_result
        end
        results
      end
    end
  end
end

像这样调用:

ActiveRecord::Base.connection.call_stored_procedure("CALL your_procedure('foo')")
于 2014-03-17T22:42:49.773 回答