この動作は現在のPHP(5.6.13)で再現可能であり、クエリはサーバーに送信されません。
あなたのケースは
0の値が期待され、1の値が指定され、ステートメントは失敗します、false
返されます。これまでのところ、文書化されているとおりに機能します。
「エラーが発生しました」と主張するかもしれません。 "は、ERRMODE_EXCEPTION
オンの場合、例外がスローされます。それは議論ですが、PDO開発者がそれに同意するかどうかは明らかではありません。
更新:
SQLCode
が選ばれる理由 設定されていませんか?
PDOソースコード、具体的にはstatic PHP_METHOD(PDOStatement, execute)
を見てください。 PDO ::execute()を処理する場合、すべてのエラーがマクロによって処理されることがわかります:PDO_HANDLE_STMT_ERR()
#define PDO_HANDLE_STMT_ERR() if (strcmp(stmt->error_code, PDO_ERR_NONE)) { pdo_handle_error(stmt->dbh, stmt TSRMLS_CC); }
重要なのは、PDOが何も期待していないときにバインドされたパラメーターを渡すと、クエリがSQLエンジンに到達しないため、SQLエンジンがSQLSTATEに伴うエラーを報告する機会がないということです。
PDO自体は偽のSQLSTATE
を作成しません それ自体では、少なくともその場合はそうではないので、stmt->error_code
PDO_ERR_NONE
にとどまります これは"00000"
です 。
例外を発生させたいことは理解できますが、 https://bugs.phpに提案する必要があります。ネット
MySQLと同じですか?
はい、ルートの動作は同じですが、MySQLドライバーではprepare
はすぐにSQLエンジンに送信されるため、列が不良であるために正しくない場合は、早期に失敗し、実際のSQLエラーが発生します。一方、PgSQLドライバーには、サーバー側のprepare
を延期する別の実装があります。 。この特定の動作については、 PHP Postgres PDOドライバーがプリペアドステートメントをサポートしていませんか?
で詳しく説明されています。
とにかく、これが私の説明を示すMySQLのケースです。つまり:
- クエリは0個のパラメータを想定しており、1個が指定されています
-
$stmt->execute
falseを返します - 例外は発生しません
- PDO::errorCodeは
00000
です
コード:
$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();
}
結果:
内部で何が起こるかというと、prepare
サーバーに送信されて成功しますが、execute
パラメータの不一致により、ステップはPDOによってキャンセルされます。
これは、クエリが存在しない列を参照しているという事実が異なる場合です。 $stmt->execute
であることを示す印刷を追加しています $stmt->prepare
によって例外が発生するため、は呼び出されません。
コード:
$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();
}
結果:
prepare
であるため、「Executingquery」ステップが発生しないことに注意してください。 それは失敗します、サーバー側。
結論
-
クエリがサーバーに送信されると、prepare()またはexecute()のどちらでも、エラーを生成するのはサーバーであるため、PDOExceptionが発生することが予想されます。
-
クエリが実行ステップのためにサーバーに送信されない場合、PDO execute()は失敗する可能性があります(falseを返します)が、例外はスローされず、
errorCode()
00000
にとどまります