pg_send_query_params返回TRUE但失败

时间:2012-09-04 22:41:51

标签: php postgresql postgis

我有一个PHP脚本,可以在Postgres DB中插入一行。它在我的测试服务器上运行正常(Postgres 9.1),但在我的新共享主机上失败了(Postgres 8.4)。

$query = "INSERT INTO " . $table . " VALUES (DEFAULT, $1, $2, CURRENT_TIMESTAMP::TIMESTAMP(0), $3, $4, ST_Point($4, $3))";
$result = pg_send_query_params($dbconn, $query, array($is_happy, $rate, $lat, $lon));

$result始终为TRUE,但未插入任何行。

我也尝试过:

$result = pg_get_result($dbconn);

但经历了同样的行为。

按照@ CraigRinger的交易建议,我也试过了两个:

$query = "BEGIN;INSERT INTO " . $table . " VALUES (DEFAULT, $1, $2, CURRENT_TIMESTAMP::TIMESTAMP(0), $3, $4, ST_Point($4, $3));COMMIT;";
$result = pg_send_query_params($dbconn, $query, array($is_happy, $rate, $lat, $lon));

pg_send_query($dbconn, "BEGIN;");
$query = "INSERT INTO " . $table . " VALUES (DEFAULT, $1, $2, CURRENT_TIMESTAMP::TIMESTAMP(0), $3, $4, ST_Point($4, $3));";
$result = pg_send_query_params($dbconn, $query, array($is_happy, $rate, $lat, $lon));
pg_send_query($dbconn, "COMMIT;");

仍然有同样的行为。

如果我在phpPgAdmin中运行INSERT查询,则会插入一行。我也可以在PHP脚本中获得此查询的结果:

"SELECT relid FROM pg_stat_user_tables"

当INSERT查询结果为true但没有插入行时,这意味着什么?可能是什么问题以及我如何解决这个问题?

修改

我可以使用phpPgAdmin INSERT行,然后使用PHP脚本中的SELECT行。

这是一个完整的PHP脚本失败(它在我的完整脚本中删除了POST收集和验证)。 rest.php脚本只保存连接变量和响应函数。此rest.php脚本适用于我的SELECT脚本:

<?php
require "KLogger.php";
require "rest.php";

ini_set("error_reporting", E_ALL ^ E_NOTICE);
ini_set("display_errors", 0);
ini_set("log_errors", 1);

$log   = KLogger::instance(dirname(__FILE__), KLogger::DEBUG);
$log_id = "AM".time();
$log->logInfo($log_id . " *** " . $_SERVER['REMOTE_ADDR']);

$lat = '51.510199';
$lon = '-0.129654';
$rate = '10';
$is_happy = 't';

$dbconn = pg_connect("host=" . $host . " dbname=" . $db . " user=" . $user . " password=" . $pw);
if(!$dbconn)
{
    $log->logInfo($log_id . " No connection: " . pg_last_error());
    sendResponse(500, "Internal Server Error");
}
else
{
    $query = "INSERT INTO " . $table . " VALUES (DEFAULT, $1, $2, CURRENT_TIMESTAMP::TIMESTAMP(0), $3, $4, ST_Point($4, $3));";
    $result = pg_send_query_params($dbconn, $query, array($is_happy, $rate, $lat, $lon));
    if(!$result)
    {
        $log->logInfo($log_id . " No Result: " . pg_last_error());
        sendResponse(500, "Internal Server Error");
    }
    else
    {
        $log->logInfo($log_id . " sendResponse(200)");
        sendResponse(200, "OK");
    }
}
pg_close($dbconn);
?>

1 个答案:

答案 0 :(得分:2)

此类问题的最常见原因是未公开的交易。

如果你BEGIN(或者通过在数据库驱动程序中关闭自动提交来隐式执行)然后做一些工作,只有完成工作的事务才能看到更改,直到它COMMIT。 / p>

如果是这种情况,那么使用相同连接的同一脚本内的立即后续查询将看到更改的行,但没有其他内容。

您还可以通过启用以下内容来检查:

log_statement = 'all'
log_line_prefix = 'db=%d pid=%p vtxid=%v txid=%x'

通过查找vtxid且无匹配BEGIN的虚拟交易ID(COMMIT)来查找不匹配的交易。

如果您无法修改postgresql.conf,因为它是共享托管,您应该能够ALTER USER myuser SET log_statement = 'all';ALTER DATABASE mydatabase SET log_statement = 'all';。您无法在log_line_prefix之外设置postgresql.conf,但您的主机可能已经设置了合理的设置。


另一种可能性 - 可能由版本差异解释的一种可能性 - 是您通过使用9.1中仅提供的功能在事务中稍后触发错误,并且您没有检测到该错误。您之前的INSERT成功,但是当后面的语句失败时,整个事务将被回滚。再次,检查服务器日志以查看。


另一个常见原因是,当您测试是否插入脚本时,您使用脚本连接的数据库与连接到的脚本不同。插入后,尝试SELECT您希望从脚本中插入的行。同样值得通过管理工具创建一个虚拟表(在你的情况下似乎是phpPgAdmin),然后测试以查看脚本是否可以看到虚拟表。