以下のように1つの更新生SQLを実行したい:
update table set f1=? where f2=? and f3=?
この SQL は によって実行されますがActiveRecord::Base.connection.execute
、動的パラメータ値をメソッドに渡す方法がわかりません。
誰か助けてくれませんか?
以下のように1つの更新生SQLを実行したい:
update table set f1=? where f2=? and f3=?
この SQL は によって実行されますがActiveRecord::Base.connection.execute
、動的パラメータ値をメソッドに渡す方法がわかりません。
誰か助けてくれませんか?
Rails API がこれを一般的に行うためのメソッドを公開しているようには見えません。基礎となる接続にアクセスして、そのメソッドを使用してみることができます (たとえば、MySQL の場合)。
st = ActiveRecord::Base.connection.raw_connection.prepare("update table set f1=? where f2=? and f3=?")
st.execute(f1, f2, f3)
st.close
これを行うことに他の影響があるかどうかはわかりません(接続が開いたままになるなど)。通常の更新の Rails コードをトレースして、実際のクエリとは別に、Rails が何をしているのかを確認します。
準備されたクエリを使用すると、データベースでの時間を少し節約できますが、これを何百万回も続けて行う場合を除き、通常の Ruby 置換を使用して更新をビルドする方がよいでしょう。
ActiveRecord::Base.connection.execute("update table set f1=#{ActiveRecord::Base.sanitize(f1)}")
または、コメント作成者が言ったように ActiveRecord を使用します。
ActiveRecord::Base.connection
quote
文字列値 (およびオプションで列オブジェクト) を取るメソッドがあります。したがって、次のように言えます。
ActiveRecord::Base.connection.execute(<<-EOQ)
UPDATE foo
SET bar = #{ActiveRecord::Base.connection.quote(baz)}
EOQ
Rails 移行または ActiveRecord オブジェクトを使用している場合は、次のように短縮できます。
connection.execute(<<-EOQ)
UPDATE foo
SET bar = #{connection.quote(baz)}
EOQ
更新: @kolen が指摘するように、exec_update
代わりに使用する必要があります。これにより、引用が処理され、メモリリークも回避されます。ただし、署名の動作は少し異なります。
connection.exec_update(<<-EOQ, "SQL", [[nil, baz]])
UPDATE foo
SET bar = $1
EOQ
ここで最後の param は、バインド パラメータを表すタプルの配列です。各タプルで、最初のエントリは列の型で、2 番目のエントリは値です。列の型を指定することはできますがnil
、Rails は通常正しいことを行います。
必要に応じてexec_query
、exec_insert
、 、もあります。exec_delete
次のようなものを使用する必要があります。
YourModel.update_all(
ActiveRecord::Base.send(:sanitize_sql_for_assignment, {:value => "'wow'"})
)
それはトリックを行うでしょう。ActiveRecord::Base#sendメソッドを使用してsanitize_sql_for_assignmentを呼び出すと、Ruby (少なくとも 1.8.7 バージョン) は、sanitize_sql_for_assignmentが実際には保護されたメソッドであるという事実をスキップします。
Rails 3.1では、クエリインターフェイスを使用する必要があります。
updateとupdate_allは、必要な操作です。
詳細はこちらをご覧ください:http://m.onkey.org/active-record-query-interface