如何在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