11

私は、Ruby on Rails、DB(MS)ドライバとストアドプロシージャの間の長年の愛憎関係に精通しており、バージョン2.3.2以降、Railsアプリケーションを開発しています。Rails(3+)ではまだストアドプロシージャはサポートされていませんか?

しかし、しばらくの間、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の設計選択ですか?

+0

FWIW:2006年2月、DHHのインタビューから:「私は、ストアドプロシージャのような派手な機能で完全に無関心です、トリガーなど - "http://dev.mysql.com/tech-resources/interviews/david-heinemeier-hansson-rails.html –

+0

また、"私はストアドプロシージャと制約を悪用し、無謀な駆逐艦の一貫性を考慮する"](http://web.archive.org/web/20060418215514/http://www.loudthinking.com/arc/000516.html)... – dbr

+7

2006 ...古代の原則(はい、6年は古代です世界一のe Rails ')は、技術の進化に対して意味を持つことはめったにありません(640kで十分です、誰ですか?) 理論的にも実用的な領域があります。理論的には私は絶対にRailsのパラダイムに立っていますが、時には最高の正規化されたデータベースは現実世界で最悪のパフォーマンスを示します。 SPが100ミリ秒未満でレポートのデータを収集して「Railsの方法」が2〜3秒かかると、共有データベースで複数のクエリが実行された場合、私は明確な勝者が誰であるか分かります。 – ChrisDekker

答えて

10

ストアドプロシージャは、レールでサポートされています。同期エラーが発生しているのは、MySQLのMULTI_STATEMENTSフラグがデフォルトでRailsで有効になっていないためです。このフラグは、複数の結果セットを返すプロシージャを可能にします。

それを有効にする方法のコードサンプルは、ここを参照してください:https://gist.github.com/wok/1367987

ストアドプロシージャは、MS SQL Serverと箱から出して動作します。

私は、mySQLとSQL Serverベースのほぼすべてのレールプロジェクトでストアドプロシージャを使用しています。

3

これは、MyClassのインスタンスを返すストアドプロシージャを実行するpostgres用です。

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()内の列リストを、モデルおよびストアドプロシージャの結果の列に置き換えます。私はこれがクラスの列を調べることによって一般化できると確信しています。

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')") 
関連する問題