sql >> Databasteknik >  >> RDS >> PostgreSQL

PDO ger inte undantag med obundna parametrar (och inga variabler i frågan)

Det beteendet är reproducerbart med nuvarande PHP (5.6.13), och frågan skickas inte ens till servern.

Ditt fall beskrivs i dokumentet som:

0 värde förväntas, 1 värde ges och satsen misslyckas, false återlämnas. Hittills fungerar som dokumenterat.

Du kan hävda att "ett fel avges " skulle antyda att när ERRMODE_EXCEPTION är på, skulle ett undantag kastas. Det är ett argument, men det är inte självklart att PDO-utvecklarna skulle hålla med om det.

Uppdatering:

Varför är SQLCode inte inställt?

Tittar på PDO-källkoden, specifikt static PHP_METHOD(PDOStatement, execute) som hanterar PDO::execute(), kan du se att alla fel hanteras av ett 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); }

Poängen är att när en bunden parameter skickas när PDO förväntade sig ingen, kommer frågan aldrig till SQL-motorn, så SQL-motorn har aldrig möjlighet att rapportera ett fel tillsammans med en SQLSTATE

PDO skapar inte i sig en falsk SQLSTATE på egen hand, åtminstone inte i så fall, såstmt->error_code stannar vid PDO_ERR_NONE vilket är "00000" .

Det är förståeligt att du föredrar att ett undantag tas upp, men då bör du föreslå det till https://bugs.php. nät

Är det samma sak med MySQL?

Ja, rotbeteendet är detsamma förutom att med MySQL-drivrutinen, prepare skickas omedelbart till SQL-motorn så om den är felaktig på grund av en dålig kolumn, misslyckas den tidigare och med ett riktigt SQL-fel. Å andra sidan har PgSQL-drivrutinen en annan implementering som gör att den skjuter upp prepare på serversidan . Detta specifika beteende diskuteras i detalj på PHP Postgres PDO-drivrutin stöder inte förberedda uttalanden?

Hur som helst, här är ett fall med MySQL som visar min förklaring, det vill säga:

  • frågan förväntar sig 0 parameter, 1 ges
  • $stmt->execute returnerar falskt
  • inga undantag tas upp
  • PDO::errorCode är 00000

Kod:

$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 som händer under huven är att prepare skickas till servern och lyckas, men execute steget avbryts av PDO på grund av att parametrarna inte matchar.

Här är ett fall som skiljer sig i det faktum att frågan hänvisar till en icke-existerande kolumn. Jag lägger till en utskrift för att visa att $stmt->execute anropas inte ens, eftersom undantaget höjs av $stmt->prepare

Kod:

$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:

Observera hur steget "Köra fråga" aldrig händer, eftersom det är prepare som misslyckas på serversidan.

Slutsats

  • när frågan skickas till servern, oavsett om det är i prepare() eller execute(), och det är servern som genererar ett fel, då kan vi förvänta oss att ett PDOException kommer att höjas.

  • när frågan inte skickas till servern för ett exekveringssteg, då kan PDO execute() misslyckas (returerar false) men inget undantag kastas och errorCode() stannar på 00000



  1. MySQL:Vänster koppling och kolumn med samma namn i olika tabeller

  2. Långsam LEFT JOIN på CTE med tidsintervall

  3. MySQL InnoDB infogningsprestanda (Windows)

  4. Skriva hebreiska till mySql med JAVA