Как выполнить необработанное обновление sql с динамическим привязкой в ​​рельсах

Я хочу выполнить одно обновление raw sql, как показано ниже:

update table set f1=? where f2=? and f3=? 

Этот SQL будет выполняться с помощью ActiveRecord::Base.connection.execute , но я не знаю, как передать значения динамических параметров в метод.

Может ли кто-нибудь помочь мне в этом?

Это не похоже, что Rails API предоставляет методы для этого в целом. Вы можете попробовать получить доступ к базовому соединению и использовать его методы, например, для MySQL:

 st = ActiveRecord::Base.connection.raw_connection.prepare("update table set f1=? where f2=? and f3=?") st.execute(f1, f2, f3) st.close 

Я не уверен, есть ли другие последствия для этого (соединения остаются открытыми и т. Д.). Я бы проследил код Rails для нормального обновления, чтобы увидеть, что он делает, помимо фактического запроса.

Использование подготовленных запросов может сэкономить вам небольшое количество времени в базе данных, но если вы делаете это миллион раз подряд, вам, вероятно, будет лучше просто создать обновление с обычной заменой Ruby, например

 ActiveRecord::Base.connection.execute("update table set f1=#{ActiveRecord::Base.sanitize(f1)}") 

или используя ActiveRecord, как говорят комментаторы.

ActiveRecord::Base.connection имеет метод quote который принимает строковое значение (и, возможно, объект столбца). Поэтому вы можете сказать следующее:

 ActiveRecord::Base.connection.execute(<<-EOQ) UPDATE foo SET bar = #{ActiveRecord::Base.connection.quote(baz)} EOQ 

Обратите внимание, что если вы используете миграцию Rails или объект ActiveRecord, вы можете сократить ее до:

 connection.execute(<<-EOQ) UPDATE foo SET bar = #{connection.quote(baz)} EOQ 

ОБНОВЛЕНИЕ: Как указывает exec_update вместо этого вы должны использовать exec_update . Это будет обрабатывать цитирование для вас, а также избежать утечки памяти. Подпись работает несколько иначе:

 connection.exec_update(<<-EOQ, "SQL", [[nil, baz]]) UPDATE foo SET bar = $1 EOQ 

Здесь последний параметр представляет собой массив кортежей, представляющих параметры привязки. В каждом кортеже первая запись представляет собой тип столбца, а вторая - значение. Вы можете nil для типа столбца, и Rails обычно будет делать правильные вещи.

Существуют также exec_query , exec_insert и exec_delete , в зависимости от того, что вам нужно.

Вы должны просто использовать что-то вроде:

 YourModel.update_all( ActiveRecord::Base.send(:sanitize_sql_for_assignment, {:value => "'wow'"}) ) 

Это сделало бы трюк. Используя метод отправки ActiveRecord :: Base # для вызова sanitize_sql_for_assignment, Ruby (по крайней мере, версия 1.8.7) пропускает тот факт, что sanitize_sql_for_assignment фактически является защищенным методом.

Когда-нибудь лучше было бы использовать имя родительского classа вместо имени таблицы:

 # Refers to the current class self.class.unscoped.where(self.class.primary_key => id).update_all(created _at: timestamp) 

Например, базовый class «Человек», подclassы (и таблицы базы данных) «Клиент» и «Продавец» Вместо этого:

 Client.where(self.class.primary_key => id).update_all(created _at: timestamp) Seller.where(self.class.primary_key => id).update_all(created _at: timestamp) 

Вы можете использовать объект базового classа следующим образом:

 person.class.unscoped.where(self.class.primary_key => id).update_all(created _at: timestamp) 

Мне нужно было использовать raw sql, потому что мне не удалось получить составные_primary_keys для работы с activerecord 2.3.8. Поэтому для доступа к таблице sqlserver 2000 с составным первичным ключом требуется необработанный sql.

 sql = "update [db].[dbo].[#{Contacts.table_name}] " + "set [COLUMN] = 0 " + "where [CLIENT_ID] = '#{contact.CLIENT_ID}' and CONTACT_ID = '#{contact.CONTACT_ID}'" st = ActiveRecord::Base.connection.raw_connection.prepare(sql) st.execute 

Если доступно лучшее решение, поделитесь им.

В Rails 3.1 вы должны использовать интерфейс запроса:

  • новые (атрибуты)
  • создавать (атрибуты)
  • создать! (атрибуты)
  • найти (id_or_array)
  • уничтожить (id_or_array)
  • destroy_all
  • удалить (id_or_array)
  • удалить все
  • обновление (ids, updates)
  • update_all (обновления)
  • существует?

update и update_all – операция, в которой вы нуждаетесь.

Подробнее см. Здесь: http://m.onkey.org/active-record-query-interface

  • Как установить контроль доступа-allow-origin в webrick под рельсами?
  • Сингулярные или множественные имена controllerов и помощников в Rails
  • Хранение массивов в базе данных: JSON и сериализованный массив
  • Включите учетную запись omniauth facebook во всплывающем окне
  • Heroku / devise - Отсутствует хост для ссылки! Укажите параметр хоста или установите default_url_options
  • Rails 4 - сильные параметры - вложенные объекты
  • Nokogiri «Не удалось создать родное расширение gem», когда я запускаю установку пакета
  • Rails 3: обертка с полем с ошибками изменяет внешний вид страницы. Как этого избежать?
  • Как настроить подтверждение электронной почты с помощью Devise?
  • Проверка URL / домена с помощью Regex? (Rails)
  • Rails: кнопки Multi-submit в одной форме
  • Давайте будем гением компьютера.