11

現在、SQLite から Postgresql に移行中ですが、この問題に遭遇しました。次の準備済みステートメントは、SQLite で機能します。

id = 5
st = ActiveRecord::Base.connection.raw_connection.prepare("DELETE FROM my_table WHERE id = ?")
st.execute(id)
st.close

残念ながら、Postgresql では動作しません。2 行目で例外がスローされます。解決策を探していたところ、次のような結果になりました。

id = 5
require 'pg'
conn = PG::Connection.open(:dbname => 'my_db_development')
conn.prepare('statement1', 'DELETE FROM my_table WHERE id = $1')
conn.exec_prepared('statement1', [ id ])

これは3行目で失敗します。このように例外を出力すると

rescue => ex

元にはこれが含まれています

{"connection":{}}

コマンドラインでSQLを実行すると機能します。私が間違っていることは何ですか?

前もって感謝します!

4

1 に答える 1

27

そのように使用したい場合prepareは、いくつかの変更を加える必要があります。

  1. PostgreSQL ドライバーは、疑問符ではなく番号付きのプレースホルダー ( $1、 、 ...) を表示する必要があるため、準備されたステートメントに名前を付ける必要があります。$2

     ActiveRecord::Base.connection.raw_connection.prepare('some_name', "DELETE FROM my_table WHERE id = $1")
    
  2. 呼び出しシーケンスの後には、次のものがprepare続きexec_preparedます。

    connection = ActiveRecord::Base.connection.raw_connection
    connection.prepare('some_name', "DELETE FROM my_table WHERE id = $1")
    st = connection.exec_prepared('some_name', [ id ])
    

上記のアプローチは、ActiveRecord と PostgreSQL で機能しPG::Connection.openます。適切に接続していれば、バージョンは機能するはずです。

別の方法は、自分で引用することです。

conn = ActiveRecord::Base.connection
conn.execute(%Q{
    delete from my_table
    where id = #{conn.quote(id)}
})

これは、通常、ActiveRecord が背後で行っていることです。

データベースと直接対話することは、Rails では少し混乱する傾向があります。

本当に干渉せずに行を削除しようとしている場合は、次を使用できますdelete

消去()

[...]

DELETE行は、レコードの主キーに対する SQL ステートメントで単純に削除され、コールバックは実行されません。

したがって、次のように言えます。

MyTable.delete(id)

シンプルなdelete from my_tables where id = ...ものをデータベースに送信します。

于 2012-12-10T18:01:23.423 に答える