关于Rails中Postgresql的准备声明

Dom*_*ber 10 sql postgresql ruby-on-rails prepared-statement ruby-on-rails-3

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

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

不幸的是它不能与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 ])
Run Code Online (Sandbox Code Playgroud)

这个在第3行失败.当我打印这样的异常时

rescue => ex
Run Code Online (Sandbox Code Playgroud)

ex包含这个

{"connection":{}}
Run Code Online (Sandbox Code Playgroud)

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

提前致谢!

mu *_*ort 25

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

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

     ActiveRecord::Base.connection.raw_connection.prepare('some_name', "DELETE FROM my_table WHERE id = $1")
    
    Run Code Online (Sandbox Code Playgroud)
  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 ])
    
    Run Code Online (Sandbox Code Playgroud)

上面的方法适用于ActiveRecord和PostgreSQL,PG::Connection.open如果你正确连接,你的版本应该可行.

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

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

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

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

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

删除()

[...]

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

所以你可以这样说:

MyTable.delete(id)
Run Code Online (Sandbox Code Playgroud)

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