Comment exécuter manuellement des commandes SQL dans Ruby On Rails à l'aide de NuoDB


142

J'essaie d'exécuter manuellement des commandes SQL pour pouvoir accéder aux procédures dans NuoDB.

J'utilise Ruby on Rails et j'utilise la commande suivante:

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

La "requête SQL" peut être n'importe quelle commande SQL.

Comme par exemple j'ai une table appelée "Feedback" et quand j'exécute la commande:

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

Cela ne renverrait qu'une "vraie" réponse au lieu de m'envoyer toutes les données demandées.

Voici le résultat de la console Rails:

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

Je voudrais utiliser ceci pour appeler des procédures stockées dans NuoDB mais en appelant les procédures, cela renverrait également une réponse "vraie".

Est-il possible d'exécuter des commandes SQL et d'obtenir les données demandées au lieu d'obtenir une réponse "vraie"?

Réponses:


166

La commande de travail que j'utilise pour exécuter des instructions SQL personnalisées est:

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

avec "foo" étant l'instruction sql (c'est-à-dire "SELECT * FROM table").

Cette commande renverra un ensemble de valeurs sous forme de hachage et les placera dans la variable de résultats.

Donc, sur mes rails application_controller.rb, j'ai ajouté ceci:

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

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

Utiliser execute_statement retournera les enregistrements trouvés et s'il n'y en a pas, il retournera nil.

De cette façon, je peux l'appeler n'importe où sur l'application rails comme par exemple:

records = execute_statement("select * from table")

"execute_statement" peut également appeler des procédures NuoDB, des fonctions et également des vues de base de données.


3
il est préférable d'utiliser exec_query si vous êtes sur PSQL car il y aura une fuite de mémoire
23inhouse

3
Je ne trouve pas la différence entre le code de votre question et celui de votre réponse. Ils semblent tous les deux utiliser ActiveRecord::Base.connection.execute. Pourriez-vous s'il vous plaît indiquer ce que vous avez exactement changé pour obtenir les données au lieu de simplement true?
RocketR

120

Pour moi, je ne pouvais pas obtenir cela pour renvoyer un hachage.

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

Mais utiliser la méthode exec_query a fonctionné.

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

10
.exec_queryrenvoie un ActiveRecord::Resultobjet très pratique avec des attributs .columnset facilement accessibles .rows. .executerenvoie un tableau de hachages qui est généralement plus difficile à gérer et probablement plus lourd en mémoire. Je ne l'avais jamais utilisé exec_query, merci pour le tuyau.
Francio Rodrigues

9
Juste pour ajouter au dernier commentaire, vous voudrez généralement utiliser .entrieslors de l'utilisation .exec_querypour obtenir les résultats sous forme de tableau de hachages.
8bithero

Cela me donne toujours nul pour les résultats avec ActiveRecord 5 exécutant une requête DELETE?
Tom Rossi

27

Republier la réponse de notre forum pour aider les autres à résoudre un problème similaire:

@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;" ) }

Le code ci-dessus est un exemple pour

  1. exécution de SQL arbitraire sur votre connexion à la base de données
  2. retour de la connexion au pool de connexions par la suite

2
Pourquoi allez-vous utiliser le pool de connexions au lieu de la connexion elle-même? Y a-t-il un avantage? Auriez-vous une source à ce sujet?
bonafernando

3
@bonafernando, Votre base de données peut commencer à générer des erreurs "Trop de connexions" si vous avez du code qui utilise ActiveRecord::Base.connectionsans appeler ActiveRecord::Base.clear_active_connections!. Voir api.rubyonrails.org/v5.2/classes/ActiveRecord/...
eremite

Ouais, avant ta réponse, j'ai changé et j'ai remarqué que je n'avais jamais eu d'autre erreur "Trop de connexions". Merci!
bonafernando le
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.