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

Lưu trữ hình ảnh trong các trường bytea trong cơ sở dữ liệu PostgreSQL

TL; DR:

Xóa addslashes($data) . Nó thừa ở đây.

Thoát kép .. hai lần

$data=fread($p,filesize($fi));
$data=addslashes($data);
$dat= pg_escape_bytea($data); 

Bạn đọc dữ liệu trong, thoát nó như thể nó là một chuỗi ký tự, sau đó chuyển đổi nó thành bytea octal hoặc hex Escape. Nó không bao giờ có thể hoạt động theo cách đó ngay cả khi pg_escape_bytea lành mạnh, mà không phải.

pg_escape_bytea của PHP dường như thoát kép đầu ra để nó có thể được chèn vào một chuỗi ký tự. Điều này cực kỳ xấu xí, nhưng dường như không có giải pháp thay thế nào không thực hiện thoát kép này, vì vậy bạn dường như không thể sử dụng các câu lệnh được tham số hóa cho bytea trong PHP. Bạn vẫn nên làm như vậy cho mọi thứ khác.

Trong trường hợp này, chỉ cần xóa addslashes dòng cho dữ liệu được đọc từ tệp là đủ.

Trường hợp kiểm tra cho thấy rằng pg_escape_bytea thoát kép (và luôn sử dụng các thoát bát phân cũ, không hiệu quả):

<?php
# oh-the-horror.php
print pg_escape_bytea("Blah binary\x00\x01\x02\x03\x04 blah");
?>

Chạy:

php oh-the-horror.php

Kết quả:

Blah binary\\000\\001\\002\\003\\004 blah

Xem các dấu gạch chéo ngược kép? Đó là bởi vì giả sử bạn sẽ nội suy nó vào SQL dưới dạng một chuỗi, điều này cực kỳ kém hiệu quả về bộ nhớ, xấu xí và là một thói quen rất xấu. Tuy nhiên, dường như bạn không có bất kỳ giải pháp thay thế nào.

Trong số những điều khác, điều này có nghĩa là:

pg_unescape_bytea(pg_escape_bytea("\x01\x02\x03"));

... tạo ra kết quả sai , kể từ pg_unescape_bytea thực ra không phải là mặt trái của pg_escape_bytea . Nó cũng làm cho không thể cấp dữ liệu đầu ra của pg_escape_bytea thành pg_query_params là một tham số, bạn phải nội suy nó trong.

Giải mã

Nếu bạn đang sử dụng PostgreSQL hiện đại, nó có thể đặt bytea_output thành hex theo mặc định. Điều đó có nghĩa là nếu tôi ghi dữ liệu của mình vào bytea sau đó tìm nạp nó trở lại, nó sẽ giống như thế này:

craig=> CREATE TABLE byteademo(x bytea);
CREATE TABLE
craig=> INSERT INTO byteademo(x) VALUES ('Blah binary\\000\\001\\002\\003\\004 blah');
INSERT 0 1
craig=> SELECT * FROM byteademo ;
                                     x                                      
----------------------------------------------------------------------------
 \x426c61682062696e6172795c3030305c3030315c3030325c3030335c30303420626c6168
(1 row)

"Ừm, cái gì", bạn có thể nói? Không sao cả, nó chỉ là biểu diễn hex nhỏ gọn hơn một chút của PostgreSQL về bytea . pg_unescape_bytea sẽ xử lý nó tốt và tạo ra các byte thô giống như đầu ra ... nếu bạn có PHP hiện đại và libpq . Trên các phiên bản cũ hơn, bạn sẽ nhận được rác và sẽ cần đặt bytea_output để escape cho pg_unescape_bytea để xử lý nó.

Thay vào đó, bạn nên làm gì

Sử dụng PDO.

Nó có hỗ trợ sane (ish) cho bytea .

$sth = $pdo->prepare('INSERT INTO mytable(somecol, byteacol) VALUES (:somecol, :byteacol)');
$sth->bindParam(':somecol', 'bork bork bork');
$sth->bindParam(':byteacol', $thebytes, PDO::PARAM_LOB);
$sth->execute();

Xem:

  • PHP:Đối tượng lớn, có ví dụ về chính xác những gì bạn muốn;
  • PDOStatement ::bindParam
  • cách lưu trữ đối tượng tuần tự hóa với không gian tên trong cơ sở dữ liệu bằng pdo php
  • Liên kết BYTEA với Tuyên bố Chuẩn bị sẵn PGSQL PDO bằng PHP5

Bạn cũng có thể muốn xem xét hỗ trợ lob (đối tượng lớn) của PostgreSQL, cung cấp giao diện trực tuyến, có thể tìm kiếm mà vẫn hoàn toàn có thể giao dịch được.

Bây giờ, chuyển sang hộp xà phòng của tôi

Nếu PHP có sự phân biệt thực sự giữa các loại "chuỗi byte" và "chuỗi văn bản", bạn thậm chí sẽ không cần pg_escape_bytea vì trình điều khiển cơ sở dữ liệu có thể làm điều đó cho bạn. Không có sự xấu xí này sẽ được yêu cầu. Thật không may, không có kiểu chuỗi và byte riêng biệt trong PHP.

Vui lòng sử dụng PDO với các câu lệnh được tham số hóa nhiều nhất có thể.

Nếu bạn không thể, ít nhất hãy sử dụng pg_query_params và các câu lệnh được tham số hóa. Dấu gạch ngang addslashes không phải là một giải pháp thay thế, nó không hiệu quả, xấu xí và không hiểu các quy tắc thoát dành riêng cho cơ sở dữ liệu. Bạn vẫn phải thoát bytea theo cách thủ công nếu bạn không sử dụng PDO vì những lý do lịch sử khó khăn, nhưng mọi thứ khác phải thông qua các câu lệnh được tham số hóa.

Để được hướng dẫn về pg_query_params :

  • Bảng Bobby, phần PHP.
  • Hướng dẫn sử dụng PHP về pg_query_params


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Tạo nhiều phiên bản Postgres trên cùng một máy

  2. Cách Pi () hoạt động trong PostgreSQL

  3. Django + Postgres:giao dịch hiện tại bị hủy bỏ, các lệnh bị bỏ qua cho đến khi kết thúc khối giao dịch

  4. Nhóm SQL theo phạm vi ngày

  5. Cách sắp xếp kết quả từ string_agg ()