Mysql 为什么Rails(3+;)仍然不支持存储过程?

Mysql 为什么Rails(3+;)仍然不支持存储过程?,mysql,ruby-on-rails,ruby-on-rails-3,stored-procedures,software-design,Mysql,Ruby On Rails,Ruby On Rails 3,Stored Procedures,Software Design,我熟悉RubyonRails、DB(MS)-驱动程序和存储过程之间长期存在的爱恨关系,从版本2.3.2开始我就一直在开发Rails应用程序 但是,偶尔会出现这样的情况:SP只是比在(速度慢得多的)应用程序级别上组合数据更好的选择。具体而言,运行合并多个表中数据的报表通常更适合SP 为什么存储过程仍然不能很好地集成到Rails或MySQL gem中。我目前正在从事一个使用Rails 3.0.10和MySQL2 gem 0.2.13的项目,但据我所知,即使是最新的Edge Rails和MySQL g

我熟悉RubyonRails、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+在使用SPs时也会发脾气

过去和现在的问题是,调用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
>ActiveRecord::Base.connection.execute(“调用存储的\u proc”)
=> #
>>ActiveRecord::Base.connection.execute(“调用存储的\u proc”)
ActiveRecord::语句无效:Mysql::错误:命令不同步;
[...]
>>ActiveRecord::Base.connection.active?
=>错误
>>ActiveRecord::Base.connection.reconnect!
=>零
>>ActiveRecord::Base.connection.execute(“调用proc01”)
=> #
>>ActiveRecord::Base.connection.active?
=>错误

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

这是由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]);

rails支持存储过程。您得到的不同步错误是因为默认情况下Rails中没有启用MySQL的
MULTI_语句
标志。此标志允许过程返回多个结果集

有关如何启用它的代码示例,请参见此处:

存储过程可以在MS SQL Server上开箱即用


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

那些出现同步错误的人可能有生成多个结果的过程。您需要执行以下操作来处理这些问题:

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

FWIW:从2006年2月开始,DHH采访:“我对存储过程、触发器等奇特的功能完全不感兴趣”--还有…2006。。。古老的原则(是的,在Rails这样的世界里,6年是古老的)很少对技术的发展有意义(640k就足够了,有人吗?)这是理论和实践领域。理论上,我绝对支持Rails范式,但有时最好的规范化数据库在现实世界中的性能最差。当一个SP可以在不到100毫秒的时间内为我的报表收集数据,并且“Rails方式”需要2-3秒的时间,并且在一个共享数据库中启动了多个查询时,我知道谁才是真正的赢家。它们与SQLServer适配器配合得很好
ActiveRecord::Base。执行\u过程(:某些\u进程名称,input1,input2)
,也许有人需要在适配器中正确地实现它?
ActiveRecord::Base.connection.call_stored_procedure("CALL your_procedure('foo')")