Mysql
 sql >> Teknologi Basis Data >  >> RDS >> Mysql

Tidak dapat memilih di mana ip=inet_pton($ip)

Pertama perbaikannya, yang cukup sederhana:Jika Anda ingin menyimpan keduanya, alamat IPv4 dan IPv6, Anda harus menggunakan VARBINARY(16) bukannya BINARY(16) .

Sekarang masalahnya:Mengapa tidak berfungsi seperti yang diharapkan dengan BINARY(16) ?

Anggap kita memiliki tabel ips dengan hanya satu kolom ip BINARY(16) PRIMARY KEY .Kami menyimpan alamat IPv4 lokal default dengan

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

dan temukan nilai berikut dalam database:

0x7F000001000000000000000000000000

Seperti yang Anda lihat - Ini adalah nilai biner 4 byte (0x7F000001 ) diisi dengan nol agar sesuai dengan kolom panjang tetap 16 byte.

Saat Anda sekarang mencoba menemukannya dengan

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

hal berikut terjadi:PHP mengirimkan nilai 0x7F000001 sebagai parameter yang kemudian dibandingkan dengan nilai yang disimpan 0x7F000001000000000000000000000000 .Tetapi karena dua nilai biner dengan panjang yang berbeda tidak pernah sama, kondisi WHERE akan selalu mengembalikan FALSE.Anda dapat mencobanya dengan

SELECT 0x00 = 0x0000

yang akan mengembalikan 0 (SALAH).

Catatan:Perilakunya berbeda untuk string non biner dengan panjang tetap (CHAR(N) ).

Kita bisa menggunakan casting eksplisit sebagai solusi:

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

dan itu akan menemukan baris. Tetapi jika kita melihat apa yang kita dapatkan

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

kita lihat saja

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

Tapi bukan itu (sebenarnya) yang kami coba simpan. Dan saat kami mencoba menyimpan 7f00:1:: , kita akan mendapatkan kesalahan kunci duplikat , meskipun kami belum pernah menyimpan alamat IPv6.

Jadi sekali lagi:Gunakan VARBINARY(16) , dan Anda dapat menyimpan kode Anda tidak tersentuh. Anda bahkan akan menghemat beberapa penyimpanan, jika Anda menyimpan banyak alamat 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. Jumlah maksimum record dalam tabel database MySQL

  2. MySQL:Tidak dapat membuat/menulis ke file '/tmp/#sql_3c6_0.MYI' (Errcode:2) - Apa artinya?

  3. Mengapa saya tidak bisa menggunakan variabel sebagai nama tabel dalam prosedur tersimpan?

  4. Cara menggunakan .htaccess untuk tautan yang indah

  5. PlanetScale &Vitess:Integritas Referensial Dengan Basis Data Sharded Legacy