Php PDO未使用未绑定参数引发异常(查询中没有变量)
所以我不知道这里发生了什么Php PDO未使用未绑定参数引发异常(查询中没有变量),php,postgresql,pdo,Php,Postgresql,Pdo,所以我不知道这里发生了什么 $link = new PDO('pgsql:dbname=' . $name . ';host=' . $host, $user, $password); $link->setAttribute(PDO::ATTR_EMULATE_PREPARES, false); $link->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); try { $stmt = $link->pr
$link = new PDO('pgsql:dbname=' . $name . ';host=' . $host, $user, $password);
$link->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$link->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
try {
$stmt = $link->prepare("SELECT s.*, d.invalid_column FROM students s ORDER BY s.student_id");
$stmt->execute(array(1));
}
catch (PDOException $e) {
print $e->getMessage();
}
当我运行这个小代码示例时,我希望抛出一个异常(因为d.invalid_column不是实列,并且我正在传递无法绑定的参数),但唯一发生的事情是execute返回false,而其他什么都没有。此外,$stmt->errorInfo()
为空,代码为00000
,这使得除了超级通用之外很难添加适当的异常抛出,而日志中没有其他内容,以帮助我在某些最终用户报告错误时跟踪错误
如果我在查询的某个地方添加了一个“?”,则会抛出正确的执行(该d.invalid_column
不是有效的列),即使我添加了更多不绑定任何内容的参数
因此,如何使此查询正确返回错误:1) 清除所有参数
2) 将“?”添加到查询中 这只是PDO中的一个bug还是什么 编辑: 将引发异常的设置(无效列):
只有当我的查询中没有
?
并将某些内容传递给execute()
时,事情才会无声地失败,PDO也没有解释。这种行为在当前的PHP(5.6.13)中是可复制的,查询甚至不会发送到服务器
您的案例描述如下:
绑定的值不能超过指定值;如果中存在更多密钥
在PDO::prepare()中指定的SQL中输入_参数,然后
语句将失败并发出错误
应为0值,给出1值,语句失败,返回false
。到目前为止,它的工作是有据可查的
您可能认为“发出错误”意味着当启用ERRMODE\u EXCEPTION
时,将引发异常。这是一个论点,但PDO开发人员是否会同意这一点并不明显
更新:
为什么未设置SQLCode
查看PDO源代码,特别是处理PDO::execute()的静态PHP_方法(PDOStatement,execute)
,您可以看到所有错误都由宏处理:PDO_HANDLE\u STMT_ERR()
关键是,当PDO期望无时传递绑定参数时,查询永远不会将其传递给SQL引擎,因此SQL引擎永远没有机会报告伴随SQLSTATE的错误
PDO本身不会自己创建一个伪的SQLSTATE
,在这种情况下至少不会,因此stmt->error\u code
停留在PDO\u ERR\u NONE
,即“00000”
您希望提出例外是可以理解的,但是您应该建议
与MySQL相同吗?
是的,根的行为是相同的,除了MySQL驱动程序外,prepare
会立即发送到SQL引擎,因此如果它因为列错误而不正确,它会更早失败,并出现真正的SQL错误。另一方面,PgSQL驱动程序有一个不同的实现,使其延迟服务器端prepare
。有关此特定行为的详细讨论,请参阅
无论如何,这里有一个MySQL的案例,演示了我的解释,即:
- 查询需要0个参数,如果给定1
返回false$stmt->execute
- 没有引发异常
- PDO::错误代码为
00000
prepare
被发送到服务器并成功,但是由于参数不匹配,execute
步骤被PDO取消
这里有一个不同的例子,查询引用了一个不存在的列。我正在添加一个打印,以显示甚至没有调用$stmt->execute
,因为异常是由$stmt->prepare
引发的
代码:
结果:
发生PDO异常DsqlState[42S22]:未找到列:1054
“字段列表”中的未知列“不存在”
请注意,“执行查询”步骤是如何从不发生的,因为服务器端的prepare
失败了
结论
- 当查询被发送到服务器时,无论是在prepare()还是execute()中,并且是服务器生成了一个错误,那么我们可以期望引发一个异常
- 当查询没有发送到服务器执行步骤时,PDO execute()可能会失败(返回false),但不会引发异常,
保持在errorCode()
00000
- 这是PDO中的一个bug,NikiC最近修复了它。请参阅bug和
问题是PDO没有检查来自
EVT_ALLOC
的错误。这是过去几个月修复的与错误报告相关的许多问题之一
如果PDO中的任何方法在异常模式下返回false而不引发异常,那么它就是一个bug。请向GitHub PR报告任何未来的错误,如果可能,请建议GitHub PR进行修复。为什么不能绑定参数?这没有任何意义。因为在本例中,它们(在
PDOStatement::execute()
中的$input_参数
)没有要绑定的对象?对于指定太多的输入参数是否会引发异常,我发现了相互矛盾的答案。使用您的原始代码,我可以确认没有引发异常。但是我确实在$stmt->errorInfo()
中看到了一个错误:字段列表中的未知列“d.invalid\u column”。实际上,我忘了包含您的setAttribute
语句。此时会引发异常:SQLSTATE[42S22]:未找到列:1054未知列“d.invalid\u Column”位于“field list”
。错误也出现在$link->errorInfo()
中。PHP可能正在评估数组(1)
a
$stmt = $link->prepare("SELECT s.*, d.invalid_column, ? FROM students s ORDER BY s.student_id");
$stmt->execute(array(1));
$stmt = $link->prepare("SELECT s.*, d.invalid_column, ? FROM students s ORDER BY s.student_id");
$stmt->execute(array(1,2,3));
$stmt = $link->prepare("SELECT s.*, d.invalid_column, ? FROM students s ORDER BY s.student_id");
$stmt->execute();
$stmt = $link->prepare("SELECT s.*, d.invalid_column FROM students s ORDER BY s.student_id");
$stmt->execute();
#define PDO_HANDLE_STMT_ERR() if (strcmp(stmt->error_code, PDO_ERR_NONE)) { pdo_handle_error(stmt->dbh, stmt TSRMLS_CC); }
$link = new PDO('mysql:dbname=' . $name . ';host=' . $host, $user, $password);
$link->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$link->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
try {
$stmt = $link->prepare("SELECT 1");
$rc=$stmt->execute(array(1));
if ($rc===false)
echo "query failed, errorCode=", $link->errorCode(), "\n";
else
echo "query succeeded, errorCode=", $link->errorCode(), "\n";
}
catch (PDOException $e) {
print "A PDOException has occurred";
print $e->getMessage();
}
$link = new PDO('mysql:dbname=' . $name . ';host=' . $host, $user, $password);
$link->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$link->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
try {
$stmt = $link->prepare("SELECT nonexisting");
echo "Executing query\n";
$rc=$stmt->execute(array(1));
if ($rc===false)
echo "query failed, errorCode=", $link->errorCode(), "\n";
else
echo "query succeeded, errorCode=", $link->errorCode(), "\n";
}
catch (PDOException $e) {
print "A PDOException has occurred";
print $e->getMessage();
}