【问题标题】:Prepared Statement on Postgresql in Rails在 Rails 中准备好关于 Postgresql 的语句
【发布时间】:2012-11-28 03:25:06
【问题描述】:

现在我正在从 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 是可行的。知道我做错了什么吗?

提前致谢!

【问题讨论】:

  • 我怎样才能找到这个?我问是因为控制台中没有关于异常的输出。

标签: sql ruby-on-rails ruby-on-rails-3 postgresql prepared-statement


【解决方案1】:

如果您想像这样使用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

删除()

[...]

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

所以你可以这样说:

MyTable.delete(id)

然后您将向数据库发送一个简单的delete from my_tables where id = ...

【讨论】:

  • 你是对的 - 给语句命名并使用美元字符而不是问号就可以了。我知道删除功能 - 在这种情况下,我正在从没有自己的模型的联合表中删除一些东西。我没有创建一个,而是选择了一个“快速”的解决方案。谢谢!
猜你喜欢
  • 2014-09-16
  • 2022-12-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多