如何在rails中使用dynamic绑定来执行原始更新sql

我想要执行一个更新原始的SQL,如下所示:

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

这个SQL将由ActiveRecord::Base.connection.execute执行,但我不知道如何将dynamic参数值传递给方法。

有人能给我任何帮助吗?

它看起来不像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代码,看看它做什么除了实际的查询。

使用准备好的查询可以节省数据库中的一小部分时间,但是除非您连续这样做了一百万次,否则最好使用普通的Rubyreplace来构build更新,例如

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

或者像评论者所说的那样使用ActiveRecord。

ActiveRecord::Base.connection有一个quote方法,它接受一个string值(也可以是列对象)。 所以你可以这样说:

 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 

你应该使用像这样的东西:

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

这会做的伎俩。 使用ActiveRecord :: Base#send方法来调用sanitize_sql_for_assignment使得Ruby(至less1.8.7版本)跳过sanitize_sql_for_assignment实际上是受保护方法的事实。

有时会更好地使用父类的名称,而不是表的名称:

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

例如,“Person”基类,子类(和数据库表)“Client”和“Seller”取而代之使用:

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

你可以通过这种方式使用基类的对象:

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

我需要使用原始的sql,因为我没有得到composite_primary_keys与activerecord 2.3.8的function。 所以为了用复合主键访问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 

如果有更好的解决scheme,请分享。

在Rails 3.1中,你应该使用查询接口:

  • 新的(属性)
  • 创build(属性)
  • 创造!(属性)
  • find(id_or_array)
  • 破坏(id_or_array)
  • destroy_all
  • 删除(id_or_array)
  • 删除所有
  • 更新(ID,更新)
  • update_all(更新)
  • 存在?

update和update_all是你需要的操作。

在这里看到细节: http : //m.onkey.org/active-record-query-interface