sql >> Database teknologi >  >> RDS >> Mysql

Kan ikke vælge hvor ip=inet_pton($ip)

Først rettelsen, som er ret enkel:Hvis du vil gemme både IPv4- og IPv6-adresser, skal du bruge VARBINARY(16) i stedet for BINÆR(16) .

Nu til problemet:Hvorfor virker det ikke som forventet med BINARY(16) ?

Overvej, at vi har en tabel ips med kun én kolonne ip BINÆR(16) PRIMÆR NØGLE .Vi gemmer den lokale standard IPv4-adresse med

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

og find følgende værdi i databasen:

0x7F000001000000000000000000000000

Som du kan se - det er en 4 byte binær værdi (0x7F000001 )højrepolstret med nuller for at passe til kolonnen med 16 bytes fast længde.

Når du nu prøver at finde den med

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

følgende sker:PHP sender værdien 0x7F000001 som parameter, som derefter sammenlignes med den gemte værdi 0x7F000001000000000000000000000000000000000000 .Men da to binære værdier af forskellig længde aldrig er ens, vil WHERE-betingelsen altid returnere FALSE. Du kan prøve det med

SELECT 0x00 = 0x0000

hvilket vil returnere 0 (FALSK).

Bemærk:Opførselen er anderledes for ikke-binære strenge med fast længde (CHAR(N) ).

Vi kunne bruge eksplicit casting som en løsning:

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

og den vil finde rækken. Men hvis vi ser på, hvad vi får

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

vi får se

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

Men det er (virkelig) ikke det, vi har forsøgt at gemme. Og når vi nu forsøger at gemme 7f00:1:: , vil vi få en dublet nøglefejl , selvom vi aldrig har gemt nogen IPv6-adresse endnu.

Så endnu en gang:Brug VARBINARY(16) , og du kan beholde din kode urørt. Du sparer endda noget lager, hvis du gemmer mange IPv4-adresser.



  1. Navigat til MySQL

  2. SQL Server - definerer en XML-type kolonne med UTF-8-kodning

  3. MySQL Ligesom flere værdier

  4. hvordan man indstiller standardværdi for teksttype i mysql