Respuestas:
No almacenar como una cadena. Use una int unsigned
columna y almacene / recupere con INET_ATON()
y INET_NTOA()
respectivamente. AFAIK mysql no es compatible con INET_ * para ipv6.
EDITAR según el comentario
El uso de la función integrada para convertir IP a / desde enteros (y almacenar esos enteros en la base de datos) tiene el efecto secundario de validar automáticamente esas IP. Digamos que almacena una IP como VARCHAR (16), debe asegurarse de no almacenar IP no válidas (como 999.999.999.999 como ejemplo) con alguna validación personalizada. Las funciones INET_ * se encargan de eso.
Probablemente sea hora de comenzar a considerar IPv6. MySQL no tiene métodos para convertir direcciones IPv6 a formato binario. Una cadena de cuarenta caracteres manejará cualquier dirección IPv6 normal. Hay un formato que podría superar los 40 caracteres, consideraría que es poco probable que ocurra la práctica.
Puede calcular el tamaño a partir de la información de que habrá como máximo 8 grupos de cuatro caracteres con 7 caracteres separadores. El formato anormal reemplaza los dos últimos grupos con una dirección de formato IPv4. Sin compresión de dirección, reemplaza los últimos 9 caracteres con hasta 15 caracteres.
Si está almacenando bloques, la indicación del tamaño del bloque puede tomar 4 caracteres en lugar de los 3 caracteres necesarios para IPv4.
Debe asegurarse de que el formato que obtiene sea consistente, pero todo el software que he visto proporciona formatos consistentes para las direcciones.
Sugeriría la migración a PostgreSQL y el uso de tipos de datos INET o CIDR .
CREATE TABLE test ( test_id serial PRIMARY KEY, address inet );
INSERT INTO test ( address ) VALUES ( '1.2.3.4'::inet );
INSERT INTO test ( address ) VALUES ( 'a:b::c:d'::inet );
SELECT * FROM test;
test_id | address
---------+----------
1 | 1.2.3.4
2 | a:b::c:d
Aquí está la mejor respuesta hecha en una de las listas de correo de MySQL. Leer Mejor FieldType para almacenar la dirección IP ... .
Brevemente sugiere, lo que segundo, usar INT (10) UNSIGNED.
Entonces, usando 192.168.10.50:
(192 * 2 ^ 24) + (168 * 2 ^ 16) + (10 * 2 ^ 8) + 50 = 3232238130 (resulta en 192.168.10.50)
En MySQL, puede usar directamente
SELECT INET_ATON('192.168.10.50');
para obtener3232238130
.
O
192 + (168 * 2 ^ 8) + (10 * 2 ^ 16) + (50 * 2 ^ 24) = 839559360 (Al revés, resulta en 50.10.168.192)
En MySQL, puede usar directamente
SELECT INET_NTOA(3232238130);
para192.168.10.50
volver.
A partir de MySQL v5.6.3 agregaron soporte para INET6_ATON
y INET6_NOTA
se encargará de las direcciones IPv4 e IPv6. Pero ya no lo almacenan como un número entero. IPv6 devuelve varbinary(16)
ay IPv4 devuelve a varbinary(4)
.
http://dev.mysql.com/doc/refman/5.6/en/miscellaneous-functions.html#function_inet6-aton
Puede almacenar hasta 15 caracteres. No utilice VARCHAR (15) porque son 16 bytes (el primer byte gestiona la longitud de la cadena y, por lo tanto, una recuperación y almacenamiento más lentos). Use CHAR (15) siempre en algo como una dirección IP.
Lo siento, no puedo comentar sobre las respuestas. Hay una pregunta al respecto en stackoverflow. Y estoy totalmente de acuerdo con la respuesta seleccionada: usar 2xBIGINT es probablemente la mejor manera para ipv6 actualmente.
Sugeriría ir por 2 * BIGINT, pero asegúrese de que estén SIN FIRMAR. Hay una especie de división natural en el límite de dirección / 64 en IPv6 (ya que a / 64 es el tamaño de bloque de red más pequeño) que se alinearía muy bien con eso.
También es posible almacenar ipv4 en estos bigints, ya sea marcando uno de ellos como NULL o utilizando el formato V4COMPAT