Quiero ejecutar una actualización de SQL sin formato como se muestra a continuación:
update table set f1=? where f2=? and f3=?
Este SQL será ejecutado por ActiveRecord::Base.connection.execute
, pero no sé cómo pasar los valores de los parámetros dinámicos al método.
¿Alguien podría ayudarme?
ruby-on-rails
activerecord
rawsql
ywenbo
fuente
fuente
Respuestas:
No parece que la API de Rails exponga métodos para hacer esto de forma genérica. Puede intentar acceder a la conexión subyacente y usar sus métodos, por ejemplo, para MySQL:
No estoy seguro de si hay otras ramificaciones para hacer esto (conexiones abiertas, etc.). Seguiría el código de Rails para una actualización normal para ver qué está haciendo aparte de la consulta real.
El uso de consultas preparadas puede ahorrarle una pequeña cantidad de tiempo en la base de datos, pero a menos que esté haciendo esto un millón de veces seguidas, probablemente sea mejor que construya la actualización con la sustitución normal de Ruby, por ejemplo
o usando ActiveRecord como dijeron los comentaristas.
fuente
field=#{value}
ya que esto lo deja abierto a ataques de inyección SQL. Si sigue ese camino, consulte el módulo ActiveRecord :: ConnectionAdapters :: Quoting .prepare
declaración en Mysql2execute
es un método peligroso y puede provocar pérdidas de memoria u otros recursos.ActiveRecord::Base.connection
tiene unquote
método que toma un valor de cadena (y opcionalmente el objeto de columna). Entonces puedes decir esto:Tenga en cuenta que si está en una migración de Rails o en un objeto ActiveRecord, puede acortarlo a:
ACTUALIZACIÓN: como señala @kolen, debería usar
exec_update
en su lugar. Esto manejará las cotizaciones por usted y también evitará pérdidas de memoria. Sin embargo, la firma funciona de manera un poco diferente:Aquí, el último parámetro es una matriz de tuplas que representan parámetros de enlace. En cada tupla, la primera entrada es el tipo de columna y la segunda es el valor. Puede ceder
nil
por el tipo de columna y Rails normalmente hará lo correcto.También hay
exec_query
,exec_insert
yexec_delete
, dependiendo de lo que necesita.fuente
execute
es un método peligroso y puede provocar pérdidas de memoria u otros recursos.on duplicate key update
todas partesON CONFLICT DO UPDATE
si lo desea. Para SQL no crudo, esta gema parece útil: github.com/jesjos/active_record_upsertDeberías usar algo como:
Eso serviría. El uso del método de envío ActiveRecord :: Base # para invocar sanitize_sql_for_assignment hace que Ruby (al menos la versión 1.8.7) omita el hecho de que sanitize_sql_for_assignment es en realidad un método protegido.
fuente
En algún momento sería mejor usar el nombre de la clase principal en lugar del nombre de la tabla:
Por ejemplo, clase base "Persona", subclases (y tablas de base de datos) "Cliente" y "Vendedor" En lugar de usar:
Puede usar el objeto de la clase base de esta manera:
fuente
¿Por qué utilizar SQL sin formato para esto?
Si tiene un modelo para usar
where
:Si no tiene un modelo para él (solo la tabla), puede crear un archivo y un modelo que heredará de
ActiveRecord::Base
y nuevamente use
where
lo mismo que el anterior:fuente
Aquí hay un truco que resolví recientemente para ejecutar sql sin procesar con enlaces:
donde
ApplicationRecord
define esto:y eso es similar a cómo AR vincula sus propias consultas.
fuente
Necesitaba usar sql sin procesar porque no logré que composite_primary_keys funcionara con activerecord 2.3.8. Entonces, para acceder a la tabla sqlserver 2000 con una clave primaria compuesta, se requería sql sin procesar.
Si hay una mejor solución disponible, compártala.
fuente
En Rails 3.1, debes usar la interfaz de consulta:
update y update_all son la operación que necesita.
Vea los detalles aquí: http://m.onkey.org/active-record-query-interface
fuente