6

W tej chwili jestem w trakcie migracji z SQLite do PostgreSQL i natknąłem się na ten problem. Poniższy przygotowana instrukcja działa z SQLite:Przygotowane oświadczenie na temat PostgreSQL w Railsach

id = 5 
st = ActiveRecord::Base.connection.raw_connection.prepare("DELETE FROM my_table WHERE id = ?") 
st.execute(id) 
st.close 

Niestety to nie działa z PostgreSQL - zgłasza wyjątek w wierszu 2. Szukałem rozwiązania i natknąłem się na to:

id = 5 
require 'pg' 
conn = PG::Connection.open(:dbname => 'my_db_development') 
conn.prepare('statement1', 'DELETE FROM my_table WHERE id = $1') 
conn.exec_prepared('statement1', [ id ]) 

ten jeden nie na linii 3. Podczas drukowania wyjątek jak to

rescue => ex 

ex zawiera ten

{"connection":{}} 

Wykonywanie SQL w linii komend działa. Każdy pomysł, co robię źle?

Z góry dziękuję!

+0

Jak mogę to znaleźć? Pytam, ponieważ w konsoli nie ma wyjścia dotyczącego wyjątku. –

Odpowiedz

20

Jeśli chcesz użyć prepare takiego wtedy będziesz musiał zrobić kilka zmian:

  1. Kierowca PostgreSQL chce zobaczyć ponumerowanych zastępcze ($1, $2 ...) nie znaki zapytania i trzeba dać przygotowane oświadczenie nazwę:

    ActiveRecord::Base.connection.raw_connection.prepare('some_name', "DELETE FROM my_table WHERE id = $1") 
    
  2. sekwencja wywołujący prepare następnie exec_prepared:

    connection = ActiveRecord::Base.connection.raw_connection 
    connection.prepare('some_name', "DELETE FROM my_table WHERE id = $1") 
    st = connection.exec_prepared('some_name', [ id ]) 
    

Powyższe podejście działa na mnie z ActiveRecord i PostgreSQL, wersja PG::Connection.open powinien działać, jeśli łączysz się prawidłowo.

Innym sposobem jest zrobić sobie przytoczyć:

conn = ActiveRecord::Base.connection 
conn.execute(%Q{ 
    delete from my_table 
    where id = #{conn.quote(id)} 
}) 

To jest coś takiego, że ActiveRecord jest zwykle robi za plecami.

Bezpośrednia interakcja z bazą danych wydaje się być trochę nieładna z Railsami, ponieważ ludzie z Railsów nie myślą, że powinieneś to zrobić.

Jeśli naprawdę są po prostu staramy się usunąć wiersz bez zakłóceń, można użyć delete:

delete()

[...]

wiersz jest po prostu usunięty za pomocą instrukcji SQL DELETE na kluczu podstawowym rekordu i nie są wykonywane żadne wywołania zwrotne.

Więc można tylko powiedzieć:

MyTable.delete(id) 

i będziesz wysyłać prosty delete from my_tables where id = ... do bazy danych.

+0

Miałeś rację - podając nazwę i użyłeś znaku dolara zamiast znaku zapytania. Zdaję sobie sprawę z funkcji usuwania - w tym przypadku usuwam coś ze wspólnej tabeli, która nie ma własnego modelu. Zamiast tworzyć takie, wybrałem "szybkie" rozwiązanie. Dzięki! –

Powiązane problemy