Ich möchte ein Update Raw SQL wie folgt ausführen:
update table set f1=? where f2=? and f3=?
Diese SQL wird von ausgeführt ActiveRecord::Base.connection.execute
, aber ich weiß nicht, wie ich die dynamischen Parameterwerte an die Methode übergeben soll.
Könnte mir jemand dabei helfen?
ruby-on-rails
activerecord
rawsql
Ywenbo
quelle
quelle
Antworten:
Es sieht nicht so aus, als würde die Rails-API Methoden bereitstellen, um dies generisch zu tun. Sie können versuchen, auf die zugrunde liegende Verbindung zuzugreifen und deren Methoden zu verwenden, z. B. für MySQL:
Ich bin mir nicht sicher, ob dies andere Konsequenzen hat (offene Verbindungen usw.). Ich würde den Rails-Code für ein normales Update verfolgen, um zu sehen, was es abgesehen von der eigentlichen Abfrage tut.
Durch die Verwendung vorbereiteter Abfragen können Sie ein wenig Zeit in der Datenbank sparen. Wenn Sie dies jedoch nicht millionenfach hintereinander tun, ist es wahrscheinlich besser, das Update nur mit normaler Ruby-Substitution zu erstellen, z
oder ActiveRecord verwenden, wie die Kommentatoren sagten.
quelle
field=#{value}
da Sie dadurch offen für SQL-Injection-Angriffe sind. Wenn Sie diesen Pfad beschreiten, überprüfen Sie das Modul ActiveRecord :: ConnectionAdapters :: Quoting .prepare
Aussage in MySQL2execute
ist eine gefährliche Methode und kann Speicher- oder andere Ressourcenlecks verursachen.ActiveRecord::Base.connection
hat einequote
Methode, die einen Zeichenfolgenwert (und optional das Spaltenobjekt) annimmt. Sie können also Folgendes sagen:Hinweis: Wenn Sie sich in einer Rails-Migration oder einem ActiveRecord-Objekt befinden, können Sie dies auf Folgendes verkürzen:
UPDATE: Wie @kolen hervorhebt, sollten Sie
exec_update
stattdessen verwenden. Dadurch wird das Angebot für Sie erledigt und es wird auch ein Speicherverlust vermieden. Die Signatur funktioniert allerdings etwas anders:Hier ist der letzte Parameter ein Array von Tupeln, die Bindungsparameter darstellen. In jedem Tupel ist der erste Eintrag der Spaltentyp und der zweite der Wert. Sie können
nil
für den Spaltentyp angeben, und Rails wird normalerweise das Richtige tun.Es gibt auch
exec_query
,exec_insert
undexec_delete
, je nachdem, was Sie brauchen.quelle
execute
ist eine gefährliche Methode und kann Speicher- oder andere Ressourcenlecks verursachen.on duplicate key update
überallON CONFLICT DO UPDATE
wenn Sie möchten . Für nicht-rohes SQL sieht dieses Juwel praktisch aus: github.com/jesjos/active_record_upsertSie sollten nur etwas verwenden wie:
Das würde den Trick machen. Mit Hilfe der Activerecord :: Base # send Methode , um die aufzurufen sanitize_sql_for_assignment macht Ruby (zumindest die 1.8.7 Version) überspringen Sie die Tatsache , dass das sanitize_sql_for_assignment tatsächlich eine geschützte Methode.
quelle
Manchmal wäre es besser, den Namen der übergeordneten Klasse anstelle des Tabellennamens zu verwenden:
Zum Beispiel "Person" Basisklasse, Unterklassen (und Datenbanktabellen) "Client" und "Verkäufer" Verwenden Sie stattdessen:
Sie können das Objekt der Basisklasse folgendermaßen verwenden:
quelle
Warum dafür Raw SQL verwenden?
Wenn Sie ein Modell dafür haben, verwenden Sie
where
:Wenn Sie kein Modell dafür haben (nur die Tabelle), können Sie eine Datei und ein Modell erstellen, von denen geerbt wird
ActiveRecord::Base
und wieder
where
das gleiche wie oben verwenden:quelle
Hier ist ein Trick, den ich kürzlich für die Ausführung von unformatiertem SQL mit Bindungen ausgearbeitet habe:
wo
ApplicationRecord
definiert dies:und das ist ähnlich wie AR seine eigenen Abfragen bindet.
quelle
Ich musste Raw SQL verwenden, weil ich nicht konnte, dass Composite_primary_keys mit Activerecord 2.3.8 funktioniert. Um mit einem zusammengesetzten Primärschlüssel auf die Tabelle sqlserver 2000 zugreifen zu können, war rohes SQL erforderlich.
Wenn eine bessere Lösung verfügbar ist, teilen Sie diese bitte mit.
quelle
In Rails 3.1 sollten Sie die Abfrageoberfläche verwenden:
update und update_all sind die Operationen, die Sie benötigen.
Details finden Sie hier: http://m.onkey.org/active-record-query-interface
quelle