6

编辑:感谢丹尼尔和丹尼斯。现在问题已经解决了,正如他们委婉地指出的那样,在这种情况下,问题出在程序员身上(特别是没有从头到尾考虑过),我希望我能同时接受这两个答案。

注意:说我是 postgresql 的新手就是侮辱新手!

我正在编写一个 Web 应用程序,它将利用 PostgreSQL 数据库进行数据存储。到目前为止,我已经很好地掌握了创建查询和从中检索结果的语法,无论是查找、删除、插入还是更新。然而,我遇到了一个难题。

为避免 SQL 注入问题,建议使用pg_prepare()/pg_execute()or pg_query_params。我使用的pg_prepare()/pg_execute()比其他的更多。但是每个查询都是一个 4 步的过程,

  1. 准备查询字符串本身,
  2. 在数据库上准备查询(使用 pg_prepare)
  3. 执行查询(pg_execute)
  4. 处理/操作返回的数据。

因为这是一个 PHP 脚本,所以准备好的查询不会在脚本终止时自动释放,因此需要通过调用手动完成,例如:

pg_query($dbconn, "DEALLOCATE 'query_name';")

但是,DEALLOCATESQL 命令不会返回有关成功或失败的有用信息,因此在尝试确定DEALLOCATE指令的结果时,尝试确定是否:

  1. 查询成功,释放也成功
  2. 查询成功,释放失败
  3. 查询失败,释放也是如此
  4. 查询失败,释放成功(我不相信这甚至会发生)

我的问题是双重的”

  1. 如何(除非重复查询服务器关于解除分配的查询)如何确定解除分配是否成功,以及
  2. 有没有一种简单的方法来确定查询的哪一部分失败(在失败的情况下)解除分配,或查询本身的发送?

这个问题提供了部分解决方案,但对找到错误的来源没有帮助。PHP/PostgreSQL:检查准备好的语句是否已经存在

4

2 回答 2

9

释放语句时,返回值pg_query指示成功与否,就像任何“实用程序语句”一样。失败时它应该返回 false。例如:

 if (!pg_query($cnx, "deallocate foobar")) {
   echo "Error deallocate: " . pg_last_error($cnx);
 }
 else {
  echo "deallocate successful";
 }

这显示:

错误解除分配:错误:准备好的语句“foobar”不存在

请注意,要解除分配的语句名称不能用单引号引起来,因为它是标识符,而不是字符串文字。如果由于有问题的字符而需要将其括起来,可以使用pg_escape_identifier(php >=5.4.4)

要清理会话,甚至没有必要遍历准备好的语句并一个一个地释放它们,您可以DEALLOCATE ALL改为调用,仍然使用pg_query.

还有另一条语句在一个查询中进行更多清理: DISCARD ALL

此外,如果脚本真的与 postgres 断开连接,这一切都不是必需的,因为准备好的语句是其父会话的本地语句,并随它而死。

当在脚本之间使用连接重用时,显式清理是必要的,无论是使用 PHP ( pg_pconnect) 的持久连接,还是像pgBouncer这样的连接池(尽管池本身可能会DISCARD ALL根据其配置进行调用)。

于 2013-11-09T13:24:57.117 回答
2

根本不需要解除分配。会话结束后,PostgreSQL 立即释放准备好的语句:http ://www.postgresql.org/docs/9.3/static/sql-deallocate.html

编辑:尽管您声称是这样,但我看不出为什么 PHP 脚本会有所不同。如果您使用池连接,那么您希望保留准备好的语句,而不是在每次运行脚本时再次编译它们。

于 2013-11-14T22:40:27.727 回答