Come eseguire manualmente i comandi SQL in Ruby On Rails usando NuoDB


142

Sto cercando di eseguire manualmente i comandi SQL in modo da poter accedere alle procedure in NuoDB.

Sto usando Ruby on Rails e sto usando il seguente comando:

ActiveRecord::Base.connection.execute("SQL query")

La "query SQL" potrebbe essere qualsiasi comando SQL.

Come ad esempio ho una tabella chiamata "Feedback" e quando eseguo il comando:

ActiveRecord::Base.connection.execute("SELECT `feedbacks`.* FROM `feedbacks`")

Ciò restituirebbe solo una risposta "vera" invece di inviarmi tutti i dati richiesti.

Questo è l'output su Rails Console:

SQL (0.4ms)  SELECT `feedbacks`.* FROM `feedbacks`
 => true

Vorrei usarlo per chiamare le procedure memorizzate in NuoDB ma dopo aver chiamato le procedure, questo restituirebbe anche una risposta "vera".

È possibile eseguire comandi SQL e ottenere i dati richiesti invece di ottenere una risposta "vera"?

Risposte:


166

Il comando funzionante che sto usando per eseguire istruzioni SQL personalizzate è:

results = ActiveRecord::Base.connection.execute("foo")

con "pippo" è l'istruzione sql (ovvero "SELEZIONA * DA tabella").

Questo comando restituirà un set di valori come hash e li inserirà nella variabile dei risultati.

Quindi sui miei binari application_controller.rb ho aggiunto questo:

def execute_statement(sql)
  results = ActiveRecord::Base.connection.execute(sql)

  if results.present?
    return results
  else
    return nil
  end
end

L'uso di execute_statement restituirà i record trovati e, se non ce ne sono, restituirà zero.

In questo modo posso semplicemente chiamarlo ovunque sull'applicazione Rails come ad esempio:

records = execute_statement("select * from table")

"execute_statement" può anche chiamare procedure, funzioni e anche visualizzazioni di database di NuoDB.


3
è meglio usare exec_query se si è su PSQL perché perderà memoria
23

3
Non riesco a trovare la differenza tra il codice nella tua domanda e nella tua risposta. Entrambi sembrano usare ActiveRecord::Base.connection.execute. Potresti indicare cosa hai modificato esattamente per ottenere i dati anziché semplicemente true?
RocketR,

120

Per me, non sono riuscito a ottenere questo per restituire un hash.

results = ActiveRecord::Base.connection.execute(sql)

Ma usando il metodo exec_query ha funzionato.

results = ActiveRecord::Base.connection.exec_query(sql)

10
.exec_queryrestituisce un ActiveRecord::Resultoggetto molto utile con attributi .columnse accessibilità facilmente accessibili .rows. .executerestituisce una serie di hash che di solito è più problematico da gestire e probabilmente più pesanti in memoria. Non l'avevo mai usato exec_query, grazie per il suggerimento.
Francio Rodrigues,

9
Solo per aggiungere l'ultimo commento, in genere si desidera utilizzare .entriesquando si utilizza .exec_queryper ottenere i risultati come una matrice di hash.
8

Questo mi dà sempre zero per i risultati con ActiveRecord 5 che esegue una query DELETE?
Tom Rossi,

27

Ripubblicare la risposta dal nostro forum per aiutare gli altri con un problema simile:

@connection = ActiveRecord::Base.connection
result = @connection.exec_query('select tablename from system.tables')
result.each do |row|
puts row
end

22
res = ActiveRecord::Base.connection_pool.with_connection { |con| con.exec_query( "SELECT 1;" ) }

Il codice sopra è un esempio di

  1. eseguire SQL arbitrario sulla connessione al database
  2. restituendo successivamente la connessione al pool di connessioni

2
Perché userete il pool di connessioni anziché la connessione stessa? C'è qualche vantaggio? Ne avresti una fonte?
bonafernando,

3
@bonafernando, Il tuo database potrebbe iniziare a generare errori "Troppe connessioni" se disponi di codice che utilizza ActiveRecord::Base.connectionsenza chiamare ActiveRecord::Base.clear_active_connections!. Vedi api.rubyonrails.org/v5.2/classes/ActiveRecord/…
eremite

Sì, prima della tua risposta ho cambiato e ho notato che non ho mai avuto altri errori "Troppe connessioni". Grazie!
bonafernando,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.