sql >> Database teknologi >  >> RDS >> PostgreSQL

PDO kaster ikke undtagelse med ubundne parametre (og ingen variabler i forespørgslen)

Denne adfærd er reproducerbar med den aktuelle PHP (5.6.13), og forespørgslen sendes ikke engang til serveren.

Din sag er beskrevet i dokumentet som:

0 værdi forventes, 1 værdi er givet, og sætningen mislykkes, false bliver returneret. Indtil videre fungerer det som dokumenteret.

Du kan hævde, at "en fejl udsendes " ville antyde, at når ERRMODE_EXCEPTION er tændt, ville en undtagelse blive kastet. Det er et argument, men det er ikke indlysende, at PDO-udviklerne ville være enige i det.

Opdatering:

Hvorfor er SQLCode ikke indstillet?

Ser på PDO-kildekoden, specifikt static PHP_METHOD(PDOStatement, execute) der håndterer PDO::execute(), kan du se, at alle fejl håndteres af en makro: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); }

Pointen er, at når en bundet parameter sendes, når PDO forventede ingen, kommer forespørgslen aldrig til SQL-motoren, så SQL-motoren har aldrig mulighed for at rapportere en fejl ledsaget af en SQLSTATE

PDO i sig selv skaber ikke en falsk SQLSTATE alene, i hvert fald ikke i det tilfælde, såstmt->error_code bliver ved PDO_ERR_NONE som er "00000" .

Det er forståeligt, at du foretrækker, at der rejses en undtagelse, men så bør du foreslå det til https://bugs.php. net

Er det det samme med MySQL?

Ja, rodadfærden er den samme, bortset fra at med MySQL-driveren er prepare sendes med det samme til SQL-motoren, så hvis den er forkert på grund af en dårlig kolonne, fejler den tidligere og med en rigtig SQL-fejl. På den anden side har PgSQL-driveren en anden implementering, der gør, at den udskyder prepare på serversiden. . Denne særlige adfærd diskuteres i detaljer på PHP Postgres PDO-driver understøtter ikke forberedt erklæring?

Uanset hvad, her er en sag med MySQL, der demonstrerer min forklaring, det vil sige:

  • forespørgslen forventer 0 parameter, 1 er givet
  • $stmt->execute returnerer falsk
  • ingen undtagelse bliver rejst
  • PDO::errorCode er 00000

Kode:

$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();
}

Resultat:

Det, der sker under emhætten, er, at prepare sendes til serveren og lykkes, men execute trin er annulleret af PDO på grund af uoverensstemmelse i parametre.

Her er et tilfælde, der adskiller sig ved, at forespørgslen refererer til en ikke-eksisterende kolonne. Jeg tilføjer en print for at vise, at $stmt->execute kaldes ikke engang, da undtagelsen er rejst af $stmt->prepare

Kode:

$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();
}

Resultat:

Bemærk, hvordan trinnet "Udførelse af forespørgsel" aldrig sker, fordi det er prepare der fejler, server-side.

Konklusion

  • når forespørgslen sendes til serveren, det være sig i prepare() eller execute(), og det er serveren, der genererer en fejl, så kan vi forvente, at en PDOException vil blive rejst.

  • når forespørgslen ikke sendes til serveren for et eksekveringstrin, så kan PDO execute() mislykkes (returnerer false), men der er ingen undtagelse, og errorCode() forbliver på 00000



  1. PDO::query() forventer, at parameter 1 er streng, objekt givet Advarsel

  2. Hvordan læser jeg dokumentationssyntaksen for PostgreSQL-kommandoer?

  3. Sådan fungerer REPLICATE()-funktionen i SQL Server (T-SQL)

  4. Vælg rækker fra MySQL-tabellen, hvor PHP-tidsstemplet er ældre end X