Wie können Sie SQL-Befehle in Ruby On Rails mithilfe von NuoDB manuell ausführen?

142

Ich versuche, SQL-Befehle manuell auszuführen, damit ich auf Prozeduren in NuoDB zugreifen kann.

Ich verwende Ruby on Rails und verwende den folgenden Befehl:

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

Die "SQL-Abfrage" kann ein beliebiger SQL-Befehl sein.

Wie zum Beispiel habe ich eine Tabelle namens "Feedback" und wenn ich den Befehl ausführe:

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

Dies würde nur eine "wahre" Antwort zurückgeben, anstatt mir alle angeforderten Daten zu senden.

Dies ist die Ausgabe auf der Rails Console:

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

Ich möchte dies verwenden, um gespeicherte Prozeduren in NuoDB aufzurufen, aber beim Aufrufen der Prozeduren würde dies auch eine "wahre" Antwort zurückgeben.

Kann ich trotzdem SQL-Befehle ausführen und die angeforderten Daten abrufen, anstatt eine "echte" Antwort zu erhalten?

Patrick Angodung
quelle

Antworten:

166

Der Arbeitsbefehl, mit dem ich benutzerdefinierte SQL-Anweisungen ausführe, lautet:

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

wobei "foo" die SQL-Anweisung ist (dh "SELECT * FROM table").

Dieser Befehl gibt eine Reihe von Werten als Hash zurück und fügt sie in die Ergebnisvariable ein.

Also habe ich auf meinen Schienen application_controller.rb Folgendes hinzugefügt:

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

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

Wenn Sie execute_statement verwenden, werden die gefundenen Datensätze zurückgegeben. Wenn keine vorhanden sind, wird null zurückgegeben.

Auf diese Weise kann ich es einfach überall in der Rails-Anwendung aufrufen, wie zum Beispiel:

records = execute_statement("select * from table")

"execute_statement" kann auch NuoDB-Prozeduren, -Funktionen und auch Datenbankansichten aufrufen.

Patrick Angodung
quelle
3
Es ist besser, exec_query zu verwenden, wenn Sie unter PSQL arbeiten, da dadurch Speicher verloren geht
23inhouse
3
Ich kann den Unterschied zwischen dem Code in Ihrer Frage und in Ihrer Antwort nicht finden. Sie scheinen beide zu benutzen ActiveRecord::Base.connection.execute. Könnten Sie bitte darauf hinweisen, was genau Sie geändert haben, um die Daten zu erhalten, anstatt nur true?
RocketR
119

Für mich konnte ich das nicht dazu bringen, einen Hash zurückzugeben.

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

Die Verwendung der exec_query-Methode hat jedoch funktioniert.

results = ActiveRecord::Base.connection.exec_query(sql)
Tim Park
quelle
10
.exec_queryGibt ein ActiveRecord::ResultObjekt zurück, das mit leicht zugänglichen Attributen .columnsund .rowsAttributen sehr praktisch ist . .executeGibt eine Reihe von Hashes zurück, die normalerweise schwieriger zu handhaben sind und wahrscheinlich mehr Speicher benötigen. Ich hatte noch nie benutzt exec_query, danke für den Tipp.
Francio Rodrigues
9
Nur um den letzten Kommentar hinzuzufügen, möchten Sie normalerweise .entriesverwenden .exec_query, um die Ergebnisse als Array von Hashes abzurufen.
8bithero
Dies gibt mir immer null für die Ergebnisse, wenn ActiveRecord 5 eine DELETE-Abfrage ausführt.
Tom Rossi
27

Reposting der Antwort aus unserem Forum, um anderen bei einem ähnlichen Problem zu helfen:

@connection = ActiveRecord::Base.connection
result = @connection.exec_query('select tablename from system.tables')
result.each do |row|
puts row
end
MFredrickson-NuoDB
quelle
22
res = ActiveRecord::Base.connection_pool.with_connection { |con| con.exec_query( "SELECT 1;" ) }

Der obige Code ist ein Beispiel für

  1. Ausführen von beliebigem SQL auf Ihrer Datenbankverbindung
  2. Anschließend wird die Verbindung wieder in den Verbindungspool zurückgeführt
Andreas Rayo Kniep
quelle
2
Warum verwenden Sie den Verbindungspool anstelle der Verbindung selbst? Gibt es einen Vorteil? Hättest du eine Quelle dazu?
Bonafernando
3
@bonafernando, Ihre Datenbank kann Fehler "Zu viele Verbindungen" auslösen, wenn Sie Code haben, der ActiveRecord::Base.connectionohne Aufruf verwendet wird ActiveRecord::Base.clear_active_connections!. Siehe api.rubyonrails.org/v5.2/classes/ActiveRecord/...
eremite
Ja, vor Ihrer Antwort habe ich mich geändert und festgestellt, dass ich noch nie einen anderen Fehler "Zu viele Verbindungen" hatte. Vielen Dank!
Bonafernando