关于Rails中Postgresql的准备声明

现在我正在从SQLite迁移到Postgresql,我遇到了这个问题。 以下准备好的语句适用于SQLite:

id = 5 st = ActiveRecord::Base.connection.raw_connection.prepare("DELETE FROM my_table WHERE id = ?") st.execute(id) st.close 

不幸的是它不能与Postgresql一起使用 – 它在第2行引发了一个例外。我一直在寻找解决方案,并且遇到了这个问题:

 id = 5 require 'pg' conn = PG::Connection.open(:dbname => 'my_db_development') conn.prepare('statement1', 'DELETE FROM my_table WHERE id = $1') conn.exec_prepared('statement1', [ id ]) 

这个在第3行失败。当我打印这样的exception时

 rescue => ex 

ex包含这个

 {"connection":{}} 

在命令行中执行SQL是有效的。 知道我做错了什么吗?

提前致谢!

如果你想使用那样的prepare ,那么你需要做一些改变:

  1. PostgreSQL驱动程序希望看到编号占位符( $1$2 ,…)不是问号,您需要为准备好的语句指定一个名称:

      ActiveRecord::Base.connection.raw_connection.prepare('some_name', "DELETE FROM my_table WHERE id = $1") 
  2. 调用序列是prepare然后是exec_prepared

     connection = ActiveRecord::Base.connection.raw_connection connection.prepare('some_name', "DELETE FROM my_table WHERE id = $1") st = connection.exec_prepared('some_name', [ id ]) 

上面的方法适用于ActiveRecord和PostgreSQL,如果你正确PG::Connection.open ,你的PG::Connection.open版本应该可以工作。

另一种方法是自己做引用:

 conn = ActiveRecord::Base.connection conn.execute(%Q{ delete from my_table where id = #{conn.quote(id)} }) 

这就是ActiveRecord通常在你背后做的事情。

直接与数据库交互往往与Rails有点混乱,因为Rails人不认为你应该这样做。

如果你真的只是试图删除没有干扰的行,你可以使用delete

删除()

[…]

只需在记录的主键上使用SQL DELETE语句删除该行,并且不执行任何回调。

所以你可以这样说:

 MyTable.delete(id) 

并且你delete from my_tables where id = ...发送一个简单的delete from my_tables where id = ...进入数据库。