11

现在我正在从 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 行失败。当我打印这样的异常时

rescue => ex

ex 包含这个

{"connection":{}}

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

提前致谢!

4

1 回答 1

27

如果您想这样使用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如果你连接正确,你的版本应该可以工作。

另一种方法是自己引用:

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

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

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

如果您真的只是想在没有干扰的情况下删除一行,您可以使用delete

删除()

[...]

使用记录的主键上的 SQLDELETE语句简单地删除该行,并且不执行任何回调。

所以你可以这样说:

MyTable.delete(id)

你会发送一个简单delete from my_tables where id = ...的到数据库中。

于 2012-12-10T18:01:23.423 回答