Quel devrait être le type de données le plus recommandé pour stocker une adresse IPv4 dans SQL Server?
Ou peut-être que quelqu'un a déjà créé un type de données utilisateur SQL (.Net Assembly)?
Je n'ai pas besoin de trier.
Le stockage d'une adresse IPv4 sous la forme d'un binary
(4) est plus fidèle à ce qu'il représente et permet une interrogation de style masque de sous-réseau facile. Cependant, il nécessite une conversion en entrée et en sortie si vous recherchez réellement une représentation textuelle. Dans ce cas, vous pouvez préférer un format de chaîne.
Une fonction SQL Server peu utilisée qui pourrait aider si vous stockez sous forme de chaîne est PARSENAME
, soit dit en passant. Non conçu pour les adresses IP mais parfaitement adapté à celles-ci. L'appel ci-dessous renverra '14':
SELECT PARSENAME('123.234.23.14', 1)
(la numérotation est de droite à gauche).
J'utilise normalement juste varchar (15) pour les adresses IPv4 - mais les trier est pénible à moins que vous ne remplissiez des zéros.
Je les ai également stockés en tant qu'INT dans le passé. System.Net.IPAddress
a une méthode GetAddressBytes
qui renverra l'adresse IP sous forme de tableau des 4 octets qui représentent l'adresse IP. Vous pouvez utiliser le code C # suivant pour convertir un IPAddress
en int
...
var ipAsInt = BitConverter.ToInt32(ip.GetAddressBytes(), 0);
Je l'avais utilisé parce que je devais faire beaucoup de recherches d'adresses de dupe, et je voulais que les index soient aussi petits et rapides que possible. Ensuite, pour extraire l'adresse de l'int et dans un objet IPAddress
dans .net, utilisez la méthode GetBytes
sur - BitConverter
pour obtenir l'int comme un tableau d'octets. Passez ce tableau d'octets au constructeur pour IPAddress
qui prend un tableau d'octets, et vous vous retrouvez avec le IPAddress
avec lequel vous avez commencé.
var myIp = new IPAddress(BitConverter.GetBytes(ipAsInt));
Concernant ce commentaire dans la réponse acceptée
les trier est pénible à moins que vous ne remplissiez des zéros.
Voici une astuce pour SQL Server 2008 (de Itzik Ben-Gan dans ce livre )
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)
Résultats
ip_address
-------------
2.12.4.4
2.12.4.169
131.33.2.201
131.33.2.202
131.107.2.201
Un de mes préférés articles explique pourquoi vous ne devriez pas utiliser d'expressions régulières pour analyser les adresses IP. La plupart de ce dont ils parlent explique vraiment pourquoi vous devriez être très prudent avec les représentations textuelles des adresses IP. Je vous suggère de le lire avant de décider quel type de données utiliser dans votre base de données, et probablement aussi pour la gestion de votre application (même si l'article est écrit sur Perl, il est utile pour n'importe quelle langue).
Je pense qu'au final, un type de données 32 bits (ou quatre types de données 8 bits) serait le meilleur choix.
La meilleure façon (quand aucun tri n'est nécessaire et aucun autre contrôle sur les adresses IP) est de le stocker en tant qu'int , le stocker en tant que varchar, etc. coûterait bien plus de performances que juste un simple int innocent.
Il existe une propriété IPAddress.Address
mais c'est obsolète, je ne sais pas pourquoi, car si vous n'avez pas besoin de trier ou de contrôler les classes IP, le meilleur moyen est de le stocker sous forme d'entier non signé (qui a une valeur maximale de 0xffffffff
ce qui équivaut à 255.255.255.255
en représentation décimale.
La classe IPAddress possède également un constructeur qui accepte un long argument.
Et selon le visualiseur du débogueur VS, cette classe IPAddress stocke elle-même sa variable interne sous la forme d'un nombre (et non d'un tableau d'octets).
En savoir plus sur les solutions de contournement stockant une unité dans MS SQL Server:
IPV4? int? ou tinyint x 4?
Cela dépend vraiment de savoir s'il s'agit simplement de stockage et de récupération ou s'il s'agit d'un critère de recherche à distance.
N'oubliez pas IPv6 - vous avez besoin de beaucoup plus de place si vous avez besoin de les stocker - 128 bits par rapport à 32 d'IPv4.
J'irais pour bigint, bien que vous ayez besoin d'un code d'aide pour traduire en versions conviviales.
Je lis beaucoup de questions similaires ici, et aucune des réponses dans celle-ci ne mentionne la réponse numéro un dans les autres: "Pour les adresses IPv4, vous pouvez les stocker comme un entier non signé et utiliser INET_ATON () et INET_NTOA () fonctionne pour renvoyer l'adresse IP à partir de sa valeur numérique, et vice versa. " Je pense que c'est ce que je vais faire avec ma base de données, sauf si je décide d'utiliser les fonctions php mentionnées ci-dessus.
Pour un stockage économe en espace et lorsque les valeurs doivent être traitées (mises en correspondance ou comparées à une plage), j'utilise un int
. L'adresse IP n'est vraiment qu'une valeur de 32 bits.
Pour une solution simple où vous voulez simplement stocker la valeur pour la visualiser, j'utilise une varchar(15)
pour stocker la représentation sous forme de chaîne de l'adresse IP.
J'ai réussi à créer quatre petites colonnes (ou le type de données entier le plus petit que vous préférez) - une pour chaque octet. Ensuite, vous pouvez créer une vue qui les écrase ensemble sous forme de chaîne de caractères (pour l'affichage) ou alors vous pouvez écrire des opérateurs simples pour déterminer qui est dans quel sous-réseau, etc.
Il est assez rapide (à condition que vous effectuiez une indexation appropriée) et permet également une interrogation très facile (pas de manipulation de chaîne!).
Puisqu'une adresse IP contient 32 bits, pouvez-vous simplement utiliser un LONG pour stocker la valeur numérique?
. il.
Le type de données le plus approprié pour stocker une adresse IPv4 dans une base de données MSSQL est un int
. Le seul petit problème est de le reconvertir en notation pointillée pour l'affichage/le tri, donc je vous recommande de créer une vue qui automatise cela pour vous.