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.