PostgreSQL
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> PostgreSQL

PDO không ném ngoại lệ với các tham số không liên kết (và không có biến trong truy vấn)

Hành vi đó có thể tái tạo với PHP hiện tại (5.6.13) và truy vấn thậm chí không được gửi đến máy chủ.

Trường hợp của bạn được mô tả trong tài liệu như:

Giá trị 0 được mong đợi, 1 giá trị được đưa ra và câu lệnh không thành công, false được trả lại. Cho đến nay, hoạt động như được ghi lại.

Bạn có thể lập luận rằng " lỗi được tạo ra "sẽ ngụ ý rằng khi ERRMODE_EXCEPTION đang bật, một ngoại lệ sẽ được ném ra. Đó là một lập luận, nhưng không rõ ràng là các nhà phát triển PDO sẽ đồng ý với nó.

Cập nhật:

Tại sao lại là SQLCode chưa đặt?

Nhìn vào mã nguồn PDO, cụ thể là static PHP_METHOD(PDOStatement, execute) xử lý PDO ::execute (), bạn có thể thấy rằng tất cả các lỗi đều được xử lý bởi macro: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); }

Vấn đề ở đây là, khi truyền một tham số bị ràng buộc khi PDO không mong đợi, truy vấn sẽ không bao giờ đến được với công cụ SQL, do đó, công cụ SQL không bao giờ có cơ hội báo cáo lỗi kèm theo SQLSTATE

Bản thân PDO không tạo SQLSTATE giả riêng nó, ít nhất là không trong trường hợp đó, vì vậy stmt->error_code vẫn ở PDO_ERR_NONE"00000" .

Có thể hiểu rằng bạn muốn một ngoại lệ được nêu ra, nhưng sau đó bạn nên đề xuất điều đó với https://bugs.php. net

Nó có giống với MySQL không?

Có, hành vi gốc giống nhau ngoại trừ với trình điều khiển MySQL, prepare được gửi ngay lập tức đến công cụ SQL, vì vậy nếu nó không chính xác do một cột không hợp lệ, nó sẽ bị lỗi sớm hơn và với một lỗi SQL thực sự. Mặt khác, trình điều khiển PgSQL có một triển khai khác khiến nó trì hoãn prepare phía máy chủ . Hành vi cụ thể này được thảo luận chi tiết tại Trình điều khiển PHP Postgres PDO không hỗ trợ câu lệnh đã soạn sẵn?

Dù sao, đây là một trường hợp với MySQL minh chứng cho lời giải thích của tôi, đó là:

  • truy vấn yêu cầu tham số 0, 1 được cung cấp
  • $stmt->execute trả về false
  • không có ngoại lệ nào được nêu ra
  • PDO ::errorCode là 00000

Mã:

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

Kết quả:

Điều gì xảy ra ẩn là prepare được gửi đến máy chủ và thành công, nhưng execute PDO đã hủy bước do thông số không khớp.

Đây là một trường hợp khác với thực tế là truy vấn đề cập đến một cột không tồn tại. Tôi đang thêm một bản in để cho thấy rằng $stmt->execute thậm chí không được gọi, vì ngoại lệ được nêu ra bởi $stmt->prepare

Mã:

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

Kết quả:

Lưu ý rằng bước "Thực thi truy vấn" không bao giờ xảy ra như thế nào, vì đó là bước prepare không thành công, phía máy chủ.

Kết luận

  • khi truy vấn được gửi đến máy chủ, có thể là ở chế độ chuẩn bị () hoặc thực thi () và chính máy chủ tạo ra lỗi, khi đó chúng ta có thể mong đợi một ngoại lệ PDOException được đưa ra.

  • khi truy vấn không được gửi đến máy chủ cho một bước thực thi, thì PDO execute () có thể không thành công (trả về false) nhưng không có ngoại lệ nào được đưa ra và errorCode() vẫn ở 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. Thêm ngày vào một ngày trong PostgreSQL

  2. Đọc tệp CSV / Excel từ tệp SFTP, thực hiện một số thay đổi trong các tệp đó bằng Pandas và lưu lại

  3. PostGIS, Có thể tạo Đa giác từ một số Điểm

  4. Thay đổi loại cột và đặt không rỗng

  5. Hiệu suất kém khi độ tương đồng của bát quái và tìm kiếm toàn văn được kết hợp với Q ind django bằng cách sử dụng postgres