Mysql
 sql >> база данни >  >> RDS >> Mysql

Не може да се избере къде ip=inet_pton($ip)

Първо корекцията, която е доста проста:Ако искате да съхранявате и двата IPv4 и IPv6 адреса, трябва да използвате VARBINARY(16) вместо BINARY(16) .

Сега към проблема:Защо не работи според очакванията с BINARY(16) ?

Помислете, че имаме таблица ips само с една колона ip BINARY(16) PRIMARY KEY .Ние съхраняваме локалния IPv4 адрес по подразбиране с

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

и намерете следната стойност в базата данни:

0x7F000001000000000000000000000000

Както виждате - това е 4 байтова двоична стойност (0x7F000001 )подпълнено отдясно с нули, за да пасне на колоната с фиксирана дължина от 16 байта.

Когато сега се опитате да го намерите с

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

се случва следното:PHP изпраща стойността 0x7F000001 като параметър, който след това се сравнява със съхранената стойност 0x7F000001000000000000000000000000 .Но тъй като две двоични стойности с различна дължина никога не са равни, условието WHERE винаги ще връща FALSE. Можете да опитате с

SELECT 0x00 = 0x0000

което ще върне 0 (НЕВЕРНО).

Забележка:Поведението е различно за недвоични низове с фиксирана дължина (CHAR(N) ).

Бихме могли да използваме изрично кастинг като заобиколно решение:

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

и ще намери реда. Но ако погледнем какво получаваме

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

ще видим

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

Но това не е (в действителност) това, което се опитахме да съхраняваме. И когато сега се опитваме да съхраняваме 7f00:1:: , ще получим грешка с дублиран ключ , въпреки че никога досега не сме съхранявали IPv6 адрес.

Така че още веднъж:Използвайте VARBINARY(16) , и можете да запазите кода си недокоснат. Дори ще спестите малко място за съхранение, ако съхранявате много 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. Как да генерирате скрипт от диаграма в MySQL Workbench

  2. MySQL данни - Най-добрият начин за прилагане на пейджинг?

  3. Как правилно да завъртите в съхранена функция на MySQL?

  4. Как да получите броя на всяка отделна стойност в колона?

  5. Не мога да инсталирам mysql2 gem