2011-02-13 10 views
45

¿Cuál es el mejor tipo de campo y longitud para almacenar direcciones IP en una base de datos MySQL?¿La mejor manera de almacenar IP en la base de datos?

¿Qué tal para IPv6?

+0

Véase la discusión aquí: http://stackoverflow.com/questions/444966/working-with-ipv6-addresses-in-php –

+0

gracias, eso es genial – Mike

Respuesta

54

tienda la ip como INT(11) UNSIGNED, a continuación, utilizar los INET_ATON y INET_NTOA funciones para almacenar/recuperar la dirección IP.

Código de ejemplo:

INSERT table(ip) VALUES (INET_ATON('192.168.0.1')); /*ip = 3232235521*/ 
SELECT INET_NTOA(ip) As IPAddress FROM table; /*IPAddress = 192.168.0.1*/ 
+6

Por el lado de PHP puede intentar '' ip2long' y long2ip' funciones. – Thai

+0

Estoy usando $ _SERVER ['REMOTE_ADDR']. Entonces, ¿debería hacer "INSERT table (ip) VALUES (INET_ATON ($ _ SERVER ['REMOTE_ADDR']));" ? – Mike

+0

@mike Sí, pero ** lo rodeo con comillas simples ** –

15

Depende de lo que quieres hacer con ella, pero probablemente la forma más sencilla sería la de presentarla como una cadena. Y this question cubre cuántos caracteres se necesitarían para manejarlo. (Es 45).

+1

Sí (+1) derecho. Actualmente tenemos dos formas de una dirección IP (IPv4 e IPv6). Quién sabe qué nuevas formas aparecerán en los próximos 20 años. Solo guárdalo como vchar y no te preocupes. –

+1

Gracias por el apoyo, Richard. No creo que tengamos que preocuparnos más allá de IPv6, pero la compatibilidad con IPv6 además de IPv4 es imprescindible. –

+1

@RichardSchneider, IPv6 está diseñado para durar más allá de 200 años – Pacerier

0

estoy totalmente de acuerdo con Scrum Meister que la manera mejor es utilizar INT(11) UNSIGNED con almacenamiento/recuperación de las funciones INET, pero a veces si no vas a estar preguntando por subred se puede optar por VARCHAR(45)

+0

¿Por qué debería tratar con las funciones INET? Básicamente, está grabando una dirección IP que se le pasó desde la pila de red. Simplemente guárdelo como se le haya dado (con suerte como una cadena). De esta forma, no tendrá que cambiar el esquema de la base de datos cuando llegue IPv8. –

+0

Estoy de acuerdo: la "mejor" manera en la práctica de la red sería usar las funciones INET para que pueda consultar por * subred * ... si no necesita este tipo de funcionalidad, su mejor opción es almacenar como una cadena que es grande suficiente para acomodar IPv6. – philwinkle

3

Si planea buscar en la base de datos por dirección IP, una INT sería mucho más rápida de consultar. Si solo está almacenando para mostrar (por ejemplo, en una salida de registro), una cadena sería mejor, ya que no necesita convertirla de un lado a otro.

5

Las direcciones IPv6 son de 128 bits (16 bytes) por lo que necesita un campo lo suficientemente grande como para almacenar eso. También es posible que necesite un campo para indicar si el IP es IPv4 o IPv6 (:: 192.168.4.10 en IPv6 es numéricamente el mismo que 192.168.4.10 en IPv4, pero dependiendo de su aplicación puede que necesite diferenciar entre los dos) .

Si necesita almacenar subredes, es posible que desee almacenar la primera dirección, la máscara CIDR y la dirección superior calculada (dirección de difusión) de la subred. Esto ayudaría en búsquedas por lo que podría hacer consultas como esta

SELECT * FROM networks WHERE lowerBound<=MYIP AND upperBound>=MYIP 

Si está utilizando subredes también se debe calcular que límite inferior a sí mismo y no sólo se basan en el usuario haciendo correctamente (pseudo código):

lowerBound = AND(networkAddress, subnetMask) 
upperBound = OR(lowerBound, complement(subnetMask)) 

Esto se aplica tanto para IPv4 como para IPv6.

6

Si desea admitir tanto IPv6 como IPv4, guárdelo como BINARY(16) y convierta la dirección IP antes de insertarla en la base de datos. Por ejemplo, en PHP (langugage comúnmente utilizado con MySQL) puede hacer esto con la función inet_pton().

Cuestiones relacionadas