Jak ręcznie wykonywać polecenia SQL w Ruby On Rails przy użyciu NuoDB

142

Próbuję ręcznie wykonywać polecenia SQL, aby uzyskać dostęp do procedur w NuoDB.

Używam Ruby on Rails i używam następującego polecenia:

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

„Zapytaniem SQL” może być dowolne polecenie SQL.

Na przykład mam tabelę o nazwie „Feedback” i kiedy wykonuję polecenie:

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

Spowoduje to tylko zwrócenie „prawdziwej” odpowiedzi zamiast przesłania mi wszystkich żądanych danych.

Oto wynik na konsoli Railsów:

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

Chciałbym użyć tego do wywołania procedur składowanych w NuoDB, ale po wywołaniu procedur zwróci to również „prawdziwą” odpowiedź.

Czy mimo wszystko mogę wykonywać polecenia SQL i uzyskać żądane dane zamiast „prawdziwej” odpowiedzi?

Patrick Angodung
źródło

Odpowiedzi:

166

Polecenie robocze, którego używam do wykonywania niestandardowych instrukcji SQL, to:

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

gdzie „foo” jest instrukcją sql (tj. „SELECT * FROM table”).

To polecenie zwróci zestaw wartości jako skrót i umieści je w zmiennej wynikowej.

Więc na moich railsach application_controller.rb dodałem to:

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

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

Użycie funkcji execute_statement zwróci znalezione rekordy, a jeśli ich nie ma, zwróci nil.

W ten sposób mogę po prostu nazwać to w dowolnym miejscu aplikacji railsowej, na przykład:

records = execute_statement("select * from table")

„execute_statement” może również wywoływać procedury NuoDB, funkcje, a także widoki bazy danych.

Patrick Angodung
źródło
3
lepiej jest użyć exec_query, jeśli korzystasz z PSQL, ponieważ spowoduje to wyciek pamięci
23inhouse,
3
Nie mogę znaleźć różnicy między kodem w Twoim pytaniu a Twoją odpowiedzią. Obaj wydają się używać ActiveRecord::Base.connection.execute. Czy mógłbyś wskazać, co dokładnie zmieniłeś, aby uzyskać dane, a nie tylko true?
RocketR
119

Dla mnie nie mogłem uzyskać tego, aby zwrócić hash.

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

Ale użycie metody exec_query zadziałało.

results = ActiveRecord::Base.connection.exec_query(sql)
Tim Park
źródło
10
.exec_queryzwraca ActiveRecord::Resultobiekt, który jest bardzo wygodny z łatwo dostępnymi .columnsi .rowsatrybutami. .executezwraca tablicę skrótów, z którymi jest zwykle trudniejszy i prawdopodobnie bardziej obciąża pamięć. Nigdy nie korzystałem exec_query, dzięki za wskazówkę.
Francio Rodrigues
9
Aby dodać do ostatniego komentarza, zwykle chciałbyś użyć .entries, .exec_queryaby uzyskać wyniki jako tablicę skrótów.
8bithero
To zawsze daje mi zero dla wyników z ActiveRecord 5 wykonującym kwerendę DELETE?
Tom Rossi,
27

Ponowne opublikowanie odpowiedzi z naszego forum, aby pomóc innym w podobnym problemie:

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

Powyższy kod jest przykładem dla

  1. wykonywanie dowolnego kodu SQL w połączeniu z bazą danych
  2. późniejsze przywrócenie połączenia z powrotem do puli połączeń
Andreas Rayo Kniep
źródło
2
Dlaczego będziesz używać puli połączeń zamiast samego połączenia? Czy jest jakaś korzyść? Czy miałbyś o tym źródło?
bonafernando
3
@bonafernando, Twoja baza danych może zacząć generować błędy „Zbyt wiele połączeń”, jeśli masz kod, który używa ActiveRecord::Base.connectionbez wywoływania ActiveRecord::Base.clear_active_connections!. Zobacz api.rubyonrails.org/v5.2/classes/ActiveRecord/...
eremita
Tak, przed twoją odpowiedzią zmieniłem się i zauważyłem, że nigdy nie miałem żadnego innego błędu „Zbyt wiele połączeń”. Dzięki!
bonafernando