Saya ingin menjalankan satu pembaruan raw sql seperti di bawah ini:
update table set f1=? where f2=? and f3=?
SQL ini akan dijalankan oleh ActiveRecord::Base.connection.execute
, tetapi saya tidak tahu cara meneruskan nilai parameter dinamis ke dalam metode.
Bisakah seseorang memberi saya bantuan?
ruby-on-rails
activerecord
rawsql
ywenbo
sumber
sumber
Jawaban:
Sepertinya Rails API tidak mengekspos metode untuk melakukan ini secara umum. Anda dapat mencoba mengakses koneksi yang mendasarinya dan menggunakan metodenya, misalnya untuk MySQL:
Saya tidak yakin apakah ada konsekuensi lain untuk melakukan ini (koneksi dibiarkan terbuka, dll). Saya akan melacak kode Rails untuk pembaruan normal untuk melihat apa yang dilakukannya selain dari kueri yang sebenarnya.
Menggunakan kueri yang telah disiapkan dapat menghemat sedikit waktu Anda di database, tetapi kecuali Anda melakukan ini jutaan kali berturut-turut, Anda mungkin lebih baik hanya membuat pembaruan dengan substitusi Ruby biasa, misalnya
atau menggunakan ActiveRecord seperti yang dikatakan para pemberi komentar.
sumber
field=#{value}
karena ini membuat Anda terbuka lebar terhadap serangan injeksi SQL. Jika Anda pergi ke jalur itu, periksa modul ActiveRecord :: ConnectionAdapters :: Quoting .prepare
pernyataan di Mysql2execute
adalah metode berbahaya dan dapat menyebabkan kebocoran memori atau sumber daya lainnya.ActiveRecord::Base.connection
memilikiquote
metode yang mengambil nilai string (dan secara opsional objek kolom). Jadi Anda bisa mengatakan ini:Perhatikan jika Anda berada dalam migrasi Rails atau objek ActiveRecord, Anda dapat mempersingkatnya menjadi:
PEMBARUAN: Seperti yang ditunjukkan @kolen, Anda harus menggunakan
exec_update
sebagai gantinya. Ini akan menangani kutipan untuk Anda dan juga menghindari kebocoran memori. Tanda tangannya bekerja sedikit berbeda:Di sini parameter terakhir adalah larik tupel yang mewakili parameter bind. Di setiap tupel, entri pertama adalah tipe kolom dan yang kedua adalah nilainya. Anda dapat memberikan
nil
untuk jenis kolom dan Rails biasanya akan melakukan hal yang benar.Ada juga
exec_query
,,exec_insert
danexec_delete
, tergantung pada apa yang Anda butuhkan.sumber
execute
adalah metode berbahaya dan dapat menyebabkan kebocoran memori atau sumber daya lainnya.on duplicate key update
manaON CONFLICT DO UPDATE
jika mau. Untuk SQL non-mentah, permata ini terlihat berguna: github.com/jesjos/active_record_upsertAnda sebaiknya menggunakan sesuatu seperti:
Itu akan berhasil. Menggunakan metode ActiveRecord :: Base # send untuk memanggil sanitize_sql_for_assignment membuat Ruby (setidaknya versi 1.8.7) mengabaikan fakta bahwa sanitize_sql_for_assignment sebenarnya adalah metode yang dilindungi.
sumber
Kadang akan lebih baik menggunakan nama kelas induk daripada nama tabel:
Misalnya kelas dasar "Orang", subkelas (dan tabel database) "Klien" dan "Penjual" Sebagai gantinya menggunakan:
Anda dapat menggunakan objek kelas dasar dengan cara ini:
sumber
Mengapa menggunakan SQL mentah untuk ini?
Jika Anda memiliki model untuk itu gunakan
where
:Jika Anda tidak memiliki model untuk itu (hanya tabel), Anda dapat membuat file dan model yang akan diwarisi
ActiveRecord::Base
dan sekali lagi gunakan
where
yang sama seperti di atas:sumber
Inilah trik yang baru-baru ini saya lakukan untuk mengeksekusi sql mentah dengan binds:
dimana
ApplicationRecord
mendefinisikan ini:dan itu mirip dengan cara AR mengikat kuerinya sendiri.
sumber
Saya perlu menggunakan sql mentah karena saya gagal mendapatkan composite_primary_keys berfungsi dengan activerecord 2.3.8. Jadi untuk mengakses tabel sqlserver 2000 dengan kunci utama komposit, diperlukan sql mentah.
Jika solusi yang lebih baik tersedia, silakan bagikan.
sumber
Di Rails 3.1, Anda harus menggunakan antarmuka kueri:
update dan update_all adalah operasi yang Anda butuhkan.
Lihat detailnya di sini: http://m.onkey.org/active-record-query-interface
sumber