PostgreSQL
 sql >> Teknologi Basis Data >  >> RDS >> PostgreSQL

PDO tidak melempar pengecualian dengan parameter tidak terikat (dan tidak ada variabel dalam kueri)

Perilaku tersebut dapat direproduksi dengan PHP saat ini (5.6.13), dan kueri bahkan tidak dikirim ke server.

Kasus Anda dijelaskan dalam dokumen sebagai:

0 nilai diharapkan, 1 nilai diberikan, dan pernyataan gagal, false dikembalikan. Sejauh ini, berfungsi seperti yang didokumentasikan.

Anda mungkin berpendapat bahwa "terjadi kesalahan " akan menyiratkan bahwa ketika ERRMODE_EXCEPTION aktif, pengecualian akan dilemparkan. Itu adalah argumen, tetapi tidak jelas bahwa pengembang PDO akan menyetujuinya.

Pembaruan:

Mengapa SQLCode tidak disetel?

Melihat kode sumber PDO, khususnya static PHP_METHOD(PDOStatement, execute) yang menangani PDO::execute(), Anda dapat melihat bahwa semua kesalahan ditangani oleh 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); }

Intinya adalah, ketika melewati parameter terikat ketika PDO tidak mengharapkan apa pun, kueri tidak pernah sampai ke mesin SQL, sehingga mesin SQL tidak pernah memiliki kesempatan untuk melaporkan kesalahan yang disertai dengan SQLSTATE

PDO sendiri tidak membuat SQLSTATE palsu sendiri, setidaknya tidak dalam kasus itu, jadistmt->error_code tetap di PDO_ERR_NONE yaitu "00000" .

Dapat dimengerti bahwa Anda lebih suka memunculkan pengecualian, tetapi Anda harus menyarankannya ke https://bugs.php. bersih

Apakah sama dengan MySQL ?

Ya, root behaviornya sama kecuali dengan driver MySQL, prepare dikirim segera ke mesin SQL jadi jika salah karena kolom yang buruk, gagal sebelumnya dan dengan kesalahan SQL nyata. Di sisi lain, driver PgSQL memiliki implementasi berbeda yang membuatnya menunda prepare sisi server . Perilaku khusus ini dibahas secara mendetail di Driver PHP Postgres PDO tidak mendukung pernyataan yang disiapkan?

Bagaimanapun, ini adalah kasus dengan MySQL yang menunjukkan penjelasan saya, yaitu:

  • kueri mengharapkan 0 parameter, 1 diberikan
  • $stmt->execute mengembalikan false
  • tidak ada pengecualian yang diangkat
  • PDO::errorCode adalah 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();
}

Hasil:

Apa yang terjadi di bawah tenda adalah bahwa prepare dikirim ke server dan berhasil, tetapi execute langkah dibatalkan oleh PDO karena ketidakcocokan parameter.

Berikut adalah kasus yang berbeda dalam kenyataan bahwa kueri merujuk ke kolom yang tidak ada. Saya menambahkan cetakan untuk menunjukkan bahwa $stmt->execute bahkan tidak dipanggil, karena pengecualian dimunculkan oleh $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();
}

Hasil:

Perhatikan bagaimana langkah "Melaksanakan kueri" tidak pernah terjadi, karena ini adalah prepare yang gagal, sisi server.

Kesimpulan

  • ketika kueri dikirim ke server, baik itu di prepare() atau execute(), dan serverlah yang menghasilkan kesalahan, maka kita dapat mengharapkan PDOException untuk dimunculkan.

  • ketika kueri tidak dikirim ke server untuk langkah eksekusi, maka eksekusi PDO() bisa gagal (mengembalikan false) tetapi tidak ada pengecualian yang dilemparkan dan errorCode() tetap di 00000



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Postgresql dapatkan hari pertama dan terakhir dari semua minggu iso di tahun tertentu

  2. Masa Depan Postgres-XL

  3. Di Django 1.9, apa konvensi untuk menggunakan JSONField (postgres jsonb asli)?

  4. Bagaimana cara saya meminta string dari JSON berdasarkan string lain di dalam JSON di PostgreSQL?

  5. Memulai dan mengisi wadah Postgres di Docker