Chcę wykonać jedną aktualizację surowego sql, jak poniżej:
update table set f1=? where f2=? and f3=?
Ten kod SQL zostanie wykonany przez ActiveRecord::Base.connection.execute
, ale nie wiem, jak przekazać wartości parametrów dynamicznych do metody.
Czy ktoś mógłby mi w tym pomóc?
ruby-on-rails
activerecord
rawsql
ywenbo
źródło
źródło
Odpowiedzi:
Wygląda na to, że API Railsów nie ujawnia metod służących do tego w sposób ogólny. Możesz spróbować uzyskać dostęp do podstawowego połączenia i użyć jego metod, np. Dla MySQL:
Nie jestem pewien, czy istnieją inne konsekwencje takiego działania (pozostawione otwarte połączenia itp.). Prześledziłbym kod Railsów dla normalnej aktualizacji, aby zobaczyć, co robi poza faktycznym zapytaniem.
Korzystanie z przygotowanych zapytań może zaoszczędzić ci trochę czasu w bazie danych, ale jeśli nie robisz tego milion razy z rzędu, prawdopodobnie lepiej byłoby po prostu zbudować aktualizację z normalnym podstawieniem Rubiego, np.
lub używając ActiveRecord, jak powiedzieli komentatorzy.
źródło
field=#{value}
ponieważ otwiera to Cię na ataki typu SQL injection. Jeśli pójdziesz tą ścieżką, sprawdź moduł ActiveRecord :: ConnectionAdapters :: Quoting .prepare
stwierdzenia w Mysql2execute
jest metodą niebezpieczną i może powodować wycieki pamięci lub innych zasobów.ActiveRecord::Base.connection
maquote
metodę, która przyjmuje wartość ciągu (i opcjonalnie obiekt kolumny). Możesz więc powiedzieć tak:Zauważ, że jeśli jesteś w migracji Railsów lub w obiekcie ActiveRecord, możesz skrócić to do:
AKTUALIZACJA: Jak wskazuje @kolen, powinieneś użyć
exec_update
zamiast tego. Spowoduje to wycenę za Ciebie, a także pozwoli uniknąć wycieku pamięci. Podpis działa jednak nieco inaczej:Tutaj ostatni parametr to tablica krotek reprezentujących parametry wiązania. W każdej krotce pierwszy wpis to typ kolumny, a drugi to wartość. Możesz podać
nil
typ kolumny, a jednak Railsy zwykle postępują właściwie.Istnieją również
exec_query
,exec_insert
iexec_delete
, w zależności od tego, czego potrzebujesz.źródło
execute
jest metodą niebezpieczną i może powodować wycieki pamięci lub innych zasobów.on duplicate key update
wszystkiegoON CONFLICT DO UPDATE
jeśli chcesz. W przypadku nie-surowego koduPowinieneś po prostu użyć czegoś takiego:
To wystarczy. Użycie metody ActiveRecord :: Base # send do wywołania sanitize_sql_for_assignment sprawia, że Ruby (przynajmniej wersja 1.8.7) pomija fakt, że sanitize_sql_for_assignment jest w rzeczywistości metodą chronioną.
źródło
Czasami lepiej byłoby użyć nazwy klasy nadrzędnej zamiast nazwy tabeli:
Na przykład klasa bazowa „Osoba”, podklasy (i tabele bazy danych) „Klient” i „Sprzedawca” Zamiast tego użyj:
Możesz użyć obiektu klasy bazowej w następujący sposób:
źródło
Po co w tym celu używać surowego SQL?
Jeśli masz model do tego użyj
where
:Jeśli nie masz dla niego modelu (tylko tabela), możesz utworzyć plik i model, które będą dziedziczyć po
ActiveRecord::Base
i ponownie użyj
where
tego samego co powyżej:źródło
Oto sztuczka, którą niedawno opracowałem, dotyczącą wykonywania surowego sql z powiązaniami:
gdzie
ApplicationRecord
to określa:i to jest podobne do tego, jak AR wiąże swoje własne zapytania.
źródło
Musiałem użyć surowego sql, ponieważ nie udało mi się uzyskać composite_primary_keys do działania z activerecord 2.3.8. Tak więc, aby uzyskać dostęp do tabeli sqlserver 2000 ze złożonym kluczem podstawowym, wymagany był surowy sql.
Jeśli dostępne jest lepsze rozwiązanie, udostępnij.
źródło
W Railsach 3.1 powinieneś używać interfejsu zapytań:
update i update_all to operacja, której potrzebujesz.
Zobacz szczegóły tutaj: http://m.onkey.org/active-record-query-interface
źródło