取消分配准备好的查询

时间:2013-11-06 02:14:35

标签: php postgresql prepared-statement

编辑:感谢丹尼尔和丹尼斯。这个问题现在得到了解决,正如他们巧妙地指出的那样,这个案例中的问题是程序员(特别是没有考虑到这一点)我希望我能接受这两个作为答案。

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

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

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

  1. 准备查询字符串本身,
  2. 在db上准备查询(使用pg_prepare)
  3. 执行查询(pg_execute)
  4. 处理/操纵返回的数据。
  5. 因为这是一个PHP脚本,所以在脚本终止时不会自动释放准备好的查询,因此需要通过以下调用手动完成:

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

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

    1. 查询成功,释放
    2. 也是如此
    3. 查询成功,解除分配失败
    4. 查询失败,释放
    5. 也失败了
    6. 查询失败,重新分配成功(我不相信甚至会发生这种情况)
    7. 我的问题是双重的“

      1. 如何(禁止对服务器重复查询解除分配的查询)我可以确定解除分配是否成功,并且
      2. 是否有一种简单的方法可以确定查询的哪一部分(如果发生故障)失败或发送查询本身?
      3. 这个问题给出了部分解决方案,但找不到错误的来源没有帮助。 PHP/PostgreSQL: check if a prepared statement already exists

2 个答案:

答案 0 :(得分:8)

取消分配语句时,pg_query的返回值表示成功与否,就像任何“实用程序语句”一样。失败时它应该返回false。例如:

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

显示:

  

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

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

来完成

要清理会话,甚至不必迭代准备好的语句并逐个取消分配,您可以改为DEALLOCATE ALL,而是pg_query

还有另一个声明在一个查询中执行更多清理: DISCARD ALL

此外,如果脚本真的与postgres断开连接,则甚至都不需要这样做,因为预准备语句是其父会话的本地语句并且随之死亡。

在脚本之间使用连接重用时,显式清理是必要的,可以是PHP(pg_pconnect)的持久连接,也可以是pgBouncer之类的连接池(尽管pooler本身可能会调用DISCARD ALL根据其配置而定。)

答案 1 :(得分:2)

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

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