2009-06-24 27 views
63

¿Cuál debería ser el tipo de datos más recomendado para almacenar una dirección IPv4 en el servidor SQL?¿Cuál es el tipo de datos más apropiado para almacenar una dirección IP en el servidor SQL?

¿O tal vez alguien ya ha creado un usuario de tipo de datos SQL (ensamblado .Net) para ello?

No necesito clasificación.

+17

No olvide IPv6 ya está aquí. Cuando analizo los registros del servidor web hoy, a veces me topo con una dirección v6 ... –

+4

¿Cómo puede ser esto un duplicado de una pregunta MÁS NUEVA? –

Respuesta

59

Almacenar una dirección IPv4 como binary (4) es lo más fiel a lo que representa, y permite consultas de estilo de máscara de subred fáciles. Sin embargo, requiere una conversión de entrada y salida si realmente busca una representación de texto. En ese caso, puede preferir un formato de cadena.

Una función SQL Server poco utilizada que podría ser útil si está almacenando como una cadena es PARSENAME, por cierto. No está diseñado para direcciones IP, pero se adapta perfectamente a ellos. La siguiente llamada devolverá '14':

SELECT PARSENAME('123.234.23.14', 1) 

(la numeración es de derecha a izquierda).

+2

Y si es necesario, también puede crear UDF para trabajar con estos datos con puntos - notación decimal ... Tal vez tanto para la entrada como para la recuperación. –

+1

Sí. O si se trabaja con un ORM, esta conversión podría completarse fácilmente, por ejemplo, un UserType en (N) Hibernate. –

+0

¿cómo hago la selección así que debería devolver una sola int? también, ¿cuánto cuesta más espacio, un único sql int o binario (4)? Entonces, ¿puedo usar el constructor IPAddress '(que toma un * long * como argumento)? ver @ mi respuesta: http://stackoverflow.com/questions/1038950/3445015#3445015 – Shimmy

-5

Citando this:

direcciones IP en una tienda (15) de columna CHAR. Dependiendo de la cantidad de datos que está almacenando, esto puede ser un desperdicio (¿por qué tenemos que almacenar los puntos?). I

+13

"esto puede ser un desperdicio" A menos que almacene todas las direcciones IP del mundo, creo que es mejor guardarlo con los puntos. "La optimización prematura es la raíz de todos los males" – tekBlues

+6

Necesita almacenar los puntos porque, de lo contrario, no sería capaz de notar la diferencia entre 127.1.1.10 y 127.1.11.0, ambos se almacenarían como 1271110. Supongo que podría almacenarlo como 4 campos de bytes separados, pero a menos que esté realmente preocupado por el ahorro de espacio para muchos datos, no creo que valga la pena el esfuerzo extra (y el procesamiento para volver a armarlos). –

+7

"12121212" es esto 12.12.12.12 o 12.121.2.12 o tal vez 12.121.21.2 o .... –

0

Probablemente vaya con varchar o .

y establecer el tamaño a 15.

+6

necesita un voto a la baja – Pacerier

25

que normalmente sólo tiene que utilizar varchar (15) para las direcciones IPv4 - pero ordenándolos es un dolor a menos que usted ceros almohadilla.

También los he almacenado como INT en el pasado. System.Net.IPAddress tiene un método GetAddressBytes que devolverá la dirección IP como una matriz de los 4 bytes que representan la dirección IP. Se puede utilizar el siguiente código C# para convertir un IPAddress a un int ...

var ipAsInt = BitConverter.ToInt32(ip.GetAddressBytes(), 0); 

que había usado esa porque tenía que hacer un montón de búsqueda de direcciones de duplicados, y quería que los índices sean tan pequeña & lo más rápido posible. Luego, para sacar la dirección del int y llevarla a un objeto IPAddress en .net, use el método GetBytes en BitConverter para obtener el int como una matriz de bytes. Pase esa matriz de bytes al constructor para IPAddress que toma una matriz de bytes y finaliza con el IPAddress con el que comenzó.

var myIp = new IPAddress(BitConverter.GetBytes(ipAsInt)); 
+3

Si está rellenando la ip, tendría más sentido usar CHAR (15) –

+0

No relleno los ceros, simplemente lo eché allí como sugerencia. –

+2

Simplemente lanzando una sugerencia también :-) –

3

IPV4? ¿En t? o tinyint x 4?

Realmente depende de si solo se trata de almacenamiento y recuperación o si se tratará de un criterio de búsqueda a distancia.

0

Dado que una dirección IP tiene 32 bits, ¿puede usar un LONG para almacenar el valor numérico?
No desperdiciaría tanto espacio como el uso de VARCHAR, pero luego tendría que decodificarlo de nuevo en una IP antes de usarlo, todo el tiempo, y la demora y la sobrecarga que los costos podrían no valer la pena.

1

Tuve cierto éxito al crear cuatro columnas smallint (o el tipo de datos entero más pequeño que prefiera) - una para cada octeto. Luego, puede hacer una vista que los una a la vez como una cadena de caracteres (para mostrar) o luego puede escribir operadores simples para determinar quién está en cada subred, etc.

Es bastante rápido (siempre que realice la indexación adecuada)) y también permite consultas realmente simples (¡sin manipulación de cadenas!).

+0

¿Por qué el voto a favor? Upvoted a contador. –

3

No se olvide de IPv6 - Se necesita mucho más espacio si es necesario almacenarlos - 128bits compara al de IPv4 32.

yo iría a bigint, aunque se necesita un código de ayuda para traducir a versiones amigables para los humanos.

2

Para un almacenamiento eficiente en el espacio y cuando los valores se van a procesar (emparejados o comparados con un rango), utilizo un int. La dirección IP realmente es solo un valor de 32 bits.

Para una solución simple en la que solo desea almacenar el valor para verla, utilizo un varchar(15) para almacenar la representación de cadena de la dirección IP.

3

Uno de mis articles habla de por qué no debería usar expresiones regulares para analizar direcciones IP. La mayor parte de lo que están diciendo realmente explica por qué debe tener mucho cuidado con las representaciones textuales de las direcciones IP. Le sugiero que lo lea antes de decidir qué tipo de datos usar en su base de datos, y probablemente también para el manejo de su aplicación (aunque el artículo esté escrito sobre Perl, es útil para cualquier idioma).

Creo que al final un tipo de datos de 32 bits (o cuatro tipos de datos de 8 bits) sería la mejor opción.

+0

Ese es un buen artículo. No he estado en perl-monks en mucho tiempo. – Yoopergeek

+0

Un poco fuera de contexto, ¿no crees? Los está serializando en la base de datos: va a controlar esa conversión sin importar el tipo de datos de la base de datos o el formato que elija. Este artículo es simplemente pedante: no veo ninguna aplicación en el mundo real de lo que está hablando. –

17

En cuanto a este comentario en la respuesta aceptada

clasificación de ellos es un dolor a menos que usted almohadilla ceros.

He aquí un truco para SQL Server 2008 (De Itzik Ben-Gan en this book)

with ip_addresses as 
(
SELECT '131.33.2.201' AS ip_address UNION ALL 
SELECT '2.12.4.4' AS ip_address UNION ALL 
SELECT '131.33.2.202' AS ip_address UNION ALL 
SELECT '2.12.4.169' AS ip_address UNION ALL 
SELECT '131.107.2.201' AS ip_address 
) 
select ip_address 
from ip_addresses 
ORDER BY CAST('/' + ip_address + '/' AS hierarchyid) 

devoluciones

ip_address 
------------- 
2.12.4.4 
2.12.4.169 
131.33.2.201 
131.33.2.202 
131.107.2.201 
+5

Oh. Ya no es la respuesta aceptada. Pero sigue siendo una técnica útil para las personas que puedan ver esta pregunta. –

3

mejor manera (cuando no hay necesidad de clasificar y otros de control en el IP) es almacenarlo como int, almacenarlo como varchar etc. costaría mucho más rendimiento que una simple inocente int.

Hay una propiedad IPAddress.Address pero está obsoleta, no sé por qué, ya que si no necesita ordenar o controlar las clases IP, la mejor manera es almacenarla como un entero sin signo (que tiene un máximo valor de 0xffffffff lo que equivale a 255.255.255.255 en representación decimal.

también la clase de dirección IP tiene un constructor que acepta un argumento largo.

Y de acuerdo con VS visualizador de depurador, que la propia clase direcciónIP almacena su variable interna como una serie (no matriz de bytes).

Leer más en soluciones de almacenamiento de una unidad en MS SQL Server:

+0

Realmente no entiendo tu primer párrafo ... ¿estás diciendo que la tienda es int o no? – Pacerier

+0

@Pacerier, Do store as 'int'. – Shimmy

+0

¿Cuál es su opinión sobre esta publicación ?: http://stackoverflow.com/questions/1385552/datatype-for-storing-ip-address-in-sql-server/1385701#1385701 – Pacerier

3

estoy leyendo un montón de preguntas similares de aquí, y ninguna de las respuestas en este, mencione la respuesta número uno en otros: "Para las direcciones IPv4, es posible que desee almacenarlas como un int unsigned y usar las funciones INET_ATON() e INET_NTOA() para devolver la dirección IP de su valor numérico, y viceversa " Creo que esto es lo que voy a hacer en mi base de datos, a menos que decida usar las funciones de PHP mencionadas anteriormente.

+3

That's MySQL .... –

-3

Soy newbie @ php, sql, pero creo que la forma más rápida de almacenar algo en sql db es convertirlo a int value y guardarlo como int.

que utiliza la función en php -

function ip_convert() { 
    $ip = $_SERVER['REMOTE_ADDR']; 
    $intip = str_replace(".","0",$ip); 
    return $intip; 
} 

y luego me basta con sustituir todos los puntos con ceros. Entonces si necesito utilizar esta IP de SQL .. si ($ ip == ip_convert())

Pero esto sólo si utiliza PHP.

+1

¿Cómo es? esto relevante para SQL Server? – cpburnz

+0

1.0.100.1 -> 10001001 100.1.0.1 -> 10001001 A menos que esté relleno con ceros en algún lugar, esto parece una idea muy mala Tenga en cuenta que podría convertir la notación de puntos en un entero de 32 bits (siempre ya que está seguro de que siempre será una dirección IPv4 y no un nombre de host o una dirección IPv6) – Foon

0

El tipo de datos más apropiado para almacenar una dirección IPv4 en una base de datos MSSQL es int. El único aspecto difícil es convertirlo a la notación punteada para mostrar/clasificar, por lo tanto, le recomiendo que cree una vista que lo automatice.

Cuestiones relacionadas