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

Không thể chọn vị trí ip =inet_pton ($ ip)

Đầu tiên, cách khắc phục khá đơn giản:Nếu bạn muốn lưu trữ cả hai địa chỉ IPv4 và IPv6, bạn nên sử dụng VARBINARY(16) thay vì BINARY(16) .

Bây giờ đến vấn đề:Tại sao nó không hoạt động như mong đợi với BINARY(16) ?

Hãy xem xét chúng ta có một bảng ips chỉ với một cột ip BINARY(16) PRIMARY KEY .Chúng tôi lưu trữ địa chỉ IPv4 cục bộ mặc định với

$stmt = $db->prepare("INSERT INTO ips(ip) VALUES(?)");
$stmt->execute([inet_pton('127.0.0.1')]);

và tìm giá trị sau trong cơ sở dữ liệu:

0x7F000001000000000000000000000000

Như bạn thấy - Đó là giá trị nhị phân 4 byte (0x7F000001 ) được đệm bên phải bằng các số không để vừa với cột có độ dài cố định 16 byte.

Khi bây giờ bạn cố gắng tìm nó bằng

$stmt = $db->prepare("SELECT * FROM ips WHERE ip = ?");
$stmt->execute([inet_pton('127.0.0.1')]);

điều sau sẽ xảy ra:PHP gửi giá trị 0x7F000001 dưới dạng tham số sau đó được so sánh với giá trị được lưu trữ 0x7F000001000000000000000000000000 Nhưng vì hai giá trị nhị phân có độ dài khác nhau không bao giờ bằng nhau nên điều kiện WHERE sẽ luôn trả về FALSE. Bạn có thể thử với

SELECT 0x00 = 0x0000

sẽ trả về 0 (SAI).

Lưu ý:Hành vi khác với các chuỗi không nhị phân có độ dài cố định (CHAR(N) ).

Chúng tôi có thể sử dụng truyền rõ ràng như một giải pháp thay thế:

$stmt = $db->prepare("SELECT * FROM ips WHERE ip = CAST(? as BINARY(16))");
$stmt->execute([inet_pton('127.0.0.1')]);

và nó sẽ tìm thấy hàng. Nhưng nếu chúng ta nhìn vào những gì chúng ta nhận được

var_dump(inet_ntop($stmt->fetch(PDO::FETCH_OBJ)->ip));

chúng ta sẽ thấy

string(8) "7f00:1::"

Nhưng đó không phải (thực sự) những gì chúng tôi đã cố gắng lưu trữ Và khi bây giờ chúng tôi cố gắng lưu trữ 7f00:1:: , chúng tôi sẽ gặp lỗi khóa trùng lặp , mặc dù chúng tôi chưa bao giờ lưu trữ bất kỳ địa chỉ IPv6 nào.

Vì vậy, một lần nữa:Sử dụng VARBINARY(16) và bạn có thể giữ nguyên mã của mình. Bạn thậm chí sẽ tiết kiệm được một số dung lượng nếu lưu trữ nhiều địa chỉ IPv4.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Cách NOT RLIKE hoạt động trong MySQL

  2. Tự động tăng không đặt lại trong MySQL

  3. Làm cách nào để Chèn nhiều bản ghi trong một lần truy cập cơ sở dữ liệu bằng cách sử dụng PDO?

  4. Làm cách nào để tìm các ký tự không phải ASCII trong MySQL?

  5. CẬP NHẬT MySQL:5 mẹo hàng đầu cho nhà phát triển T-SQL