6

In questo momento sono nel mezzo della migrazione da SQLite a Postgresql e mi sono imbattuto in questo problema. La seguente dichiarazione preparata lavora con SQLite:Dichiarazione preparata su Postgresql in Rails

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

Purtroppo non funziona con PostgreSQL - viene generata un'eccezione alla linea 2. ero alla ricerca di soluzioni e sono imbattuto in questo:

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 ]) 

Questo uno non riesce alla linea 3. Quando stampo eccezione come questo

rescue => ex 

ex contiene questo

{"connection":{}} 

L'esecuzione di SQL in una riga di comando funziona. Qualche idea su cosa sto facendo male?

Grazie in anticipo!

+0

Come posso trovare questo fuori? Sto chiedendo perché non c'è uscita nella console riguardo un'eccezione. –

risposta

20

Se si desidera utilizzare prepare del genere, allora avrete bisogno di fare un paio di modifiche:

  1. Il driver PostgreSQL vuole vedere segnaposto numerati ($1, $2, ...), non in punti interrogativi ed è necessario dare la vostra dichiarazione preparata un nome:

    ActiveRecord::Base.connection.raw_connection.prepare('some_name', "DELETE FROM my_table WHERE id = $1") 
    
  2. La sequenza di chiamata è prepare seguito da 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 ]) 
    

L'approccio di cui sopra funziona per me con ActiveRecord e PostgreSQL, la versione PG::Connection.open dovrebbe funzionare se si sta collegando correttamente.

Un altro modo è quello di fare la citazione da soli:

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

Questo è il genere di cose che ActiveRecord è di solito facendo dietro la schiena.

L'interazione diretta con il database tende a essere un po 'caos con Rails dal momento che i Rails non pensano che dovresti mai farlo.

Se davvero sta solo cercando di eliminare una riga senza interferenze, è possibile utilizzare delete:

delete()

[...]

La riga è semplicemente rimosso con un'istruzione SQL DELETE sulla chiave primaria del record e nessuna richiamata viene eseguita.

Così si può solo dire questo:

MyTable.delete(id) 

e ti inviare una semplice delete from my_tables where id = ... nel database.

+0

Avevi ragione: dare un nome alla dichiarazione e usare un carattere dollaro invece di un punto interrogativo ha fatto il lavoro. Sono a conoscenza della funzione di cancellazione - in questo caso sto eliminando qualcosa da una tabella comune che non ha il proprio modello. Piuttosto che crearne uno, ho optato per una soluzione "rapida". Grazie! –