sql >> Database >  >> RDS >> Mysql

Kan niet selecteren waar ip=inet_pton($ip)

Eerst de oplossing, die vrij eenvoudig is:als u zowel IPv4- als IPv6-adressen wilt opslaan, moet u VARBINARY(16) gebruiken in plaats van BINARY(16) .

Nu het probleem:waarom werkt het niet zoals verwacht met BINARY(16) ?

Overweeg dat we een tabel hebben ips met slechts één kolom ip BINARY(16) PRIMARY KEY .We slaan het standaard lokale IPv4-adres op met

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

en zoek de volgende waarde in de database:

0x7F000001000000000000000000000000

Zoals je ziet - Het is een binaire waarde van 4 bytes (0x7F000001 )rechts opgevuld met nullen om in de kolom met vaste lengte van 16 bytes te passen.

Wanneer je het nu probeert te vinden met

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

het volgende gebeurt:PHP stuurt de waarde 0x7F000001 als parameter die vervolgens wordt vergeleken met de opgeslagen waarde 0x7F000001000000000000000000000000 .Maar aangezien twee binaire waarden van verschillende lengte nooit gelijk zijn, zal de WHERE-voorwaarde altijd FALSE retourneren. U kunt het proberen met

SELECT 0x00 = 0x0000

wat 0 zal opleveren (FALSE).

Opmerking:het gedrag is anders voor niet-binaire tekenreeksen met een vaste lengte (CHAR(N) ).

We zouden expliciet casten als tijdelijke oplossing kunnen gebruiken:

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

en het zal de rij vinden. Maar als we kijken naar wat we krijgen

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

we zullen zien

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

Maar dat is niet (echt) wat we hebben geprobeerd op te slaan. En als we nu 7f00:1:: proberen op te slaan , krijgen we een fout met dubbele sleutel , hoewel we nog nooit een IPv6-adres hebben opgeslagen.

Dus nogmaals:gebruik VARBINARY(16) , en u kunt uw code ongewijzigd laten. U bespaart zelfs wat opslagruimte als u veel IPv4-adressen opslaat.



  1. Standaard tekencodering van SQL Server

  2. Tel het aantal voorkomens van een string in een VARCHAR-veld?

  3. SQLSTATE [HY093]:pdo-instructie tijdens invoegen in mysql db

  4. TNS-12505:TNS:luisteraar kent momenteel geen SID die is opgegeven in de verbindingsdescriptor