Какой тип данных наиболее подходит для хранения IP-адреса на сервере SQL? [Дубликат]

В дополнение к полезному ответу @ Avinash Raj с более общим решением, совместимым с POSIX.

  • Включает комментирование строк
  • Также указывается символ комментария (строка).

Обратите внимание, что решение равно awk ], потому что надежное портативное решение с sed практически невозможно из-за ограничений правильных выражений POSIX ' basic .

awk -v commentId='#' -v word='2001' '
  $0 ~ "(^|[[:punct:][:space:]])" word "($|[[:punct:][:space:]])" { 
    if (match($0, "^[[:space:]]*" commentId))
      $0 = substr($0, RSTART + RLENGTH)
    else
      $0 = commentId $0
  } 
  { print }
  ' file > tmpfile.$$ && mv tmpfile.$$ file
  • (^|[[:punct:][:space:]]) и ($|[[:punct:][:space:]]) являются расширенными эквивалентами регулярных выражений POSIX в словарных границах \< и \>, известных из других диалектов regex.
  • Пробелы после символ комментария сохраняется, но не до него.
  • При добавлении символа комментария к строке он непосредственно добавляется без пробелов.
  • Таким образом, если вы только переключаете комментарии к этому решению, все пробелы сохраняются.
  • POSIX awk не предлагает на месте (также не относится к POSIX sed), поэтому вывод сначала фиксируется во временном файле, и этот файл затем заменяет оригинал на успех.

65
задан Community 27 June 2012 в 23:53
поделиться

13 ответов

Сохранение IPv4-адреса в виде двоичного файла (4) наиболее точно соответствует тому, что он представляет, и позволяет легко Запросы в стиле маски подсети. Однако он требует преобразования внутрь и обратно, если вы действительно хотите текстовое представление. В этом случае вы можете предпочесть строковый формат.

Между прочим, мало используемая функция SQL Server, которая может помочь, если вы сохраняете как строку, - это PARSENAME . Не предназначен для IP-адресов, но идеально для них подходит. Приведенный ниже вызов вернет «14»:

SELECT PARSENAME('123.234.23.14', 1)

(нумерация справа налево).

он требует преобразования внутрь и обратно, если вы действительно хотите текстовое представление. В этом случае вы можете предпочесть строковый формат.

Между прочим, мало используемая функция SQL Server, которая может помочь, если вы сохраняете как строку, - это PARSENAME . Не предназначен для IP-адресов, но идеально для них подходит. Приведенный ниже вызов вернет «14»:

SELECT PARSENAME('123.234.23.14', 1)

(нумерация справа налево).

он требует преобразования внутрь и обратно, если вы действительно хотите текстовое представление. В этом случае вы можете предпочесть строковый формат.

Между прочим, мало используемая функция SQL Server, которая может помочь, если вы сохраняете как строку, - это PARSENAME . Не предназначен для IP-адресов, но идеально для них подходит. Приведенный ниже вызов вернет «14»:

SELECT PARSENAME('123.234.23.14', 1)

(нумерация справа налево).

61
ответ дан 24 November 2019 в 15:26
поделиться

Цитирование это :

Сохранение IP-адресов в столбце CHAR (15). В зависимости от того, сколько данных вы храните, это может быть довольно расточительным (зачем нам хранить точки?). I

-4
ответ дан 24 November 2019 в 15:26
поделиться

Мне удалось создать четыре столбца smallint (или любого другого типа небольших целочисленных данных, который вы предпочитаете) - по одному для каждого октета. Затем вы можете создать представление, которое объединяет их в виде строки символов (для отображения), или затем вы можете написать простые операторы, чтобы определить, кто все в какой подсети и т. Д.

Это довольно быстро (при условии правильной индексации) а также позволяет очень легко выполнять запросы (без манипуляций со строками!).

1
ответ дан 24 November 2019 в 15:26
поделиться

Не забывайте про IPv6 - вам понадобится гораздо больше места, если вам нужно их хранить - 128 бит по сравнению с 32 в IPv4.

Я бы выбрал bigint, хотя вам понадобится некоторый вспомогательный код для перевода в удобные для человека версии.

3
ответ дан 24 November 2019 в 15:26
поделиться

Я бы, вероятно, выбрал varchar или char .

И установил размер 15.

-1
ответ дан 24 November 2019 в 15:26
поделиться

IPV4? int? или tinyint x 4?

Это действительно зависит от того, будет ли это просто хранение и извлечение или это будет критерий ранжированного поиска.

3
ответ дан 24 November 2019 в 15:26
поделиться

Поскольку в IP-адресе 32 бита, можете ли вы просто использовать LONG для хранения числового значения?
Это не будет так расточительно, как использование VARCHAR, но тогда вам придется каждый раз декодировать его обратно в IP, прежде чем использовать его, а задержка и накладные расходы могут не окупиться.

0
ответ дан 24 November 2019 в 15:26
поделиться

В одной из моих любимых статей рассказывается о том, почему не следует использовать регулярные выражения для анализа IP-адресов. Большая часть того, о чем они говорят, действительно объясняет, почему вы должны быть очень осторожны с текстовым представлением IP-адресов. Я предлагаю вам прочитать его, прежде чем решать, какой тип данных использовать в вашей базе данных, и, вероятно, также для любой обработки вашего приложения (хотя статья написана о Perl, она полезна для любого языка).

Я думаю, что в конец 32-битный тип данных (или четыре 8-битных типа данных) будет лучшим выбором.

4
ответ дан 24 November 2019 в 15:26
поделиться

Для эффективного хранения данных и когда значения должны быть обработаны (сопоставлены или сравниваются с диапазоном), я использую int . IP-адрес на самом деле представляет собой 32-битное значение.

Для простого решения, когда вы просто хотите сохранить значение для его просмотра, я использую varchar (15) для хранения строкового представления IP-адрес.

2
ответ дан 24 November 2019 в 15:26
поделиться

Обычно я просто использую varchar (15) для адресов IPv4, но сортировка их - это боль, если вы не добавляете нули.

Я также хранил их как INT в прошлом. System.Net.IPAddress имеет метод GetAddressBytes , который возвращает IP-адрес в виде массива из 4 байтов, представляющих IP-адрес. Вы можете использовать следующий код C # для преобразования IPAddress в int ...

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

Я использовал это, потому что мне пришлось много искать дублированные адреса, и хотел, чтобы индексы были как можно меньше и быстрее. Затем, чтобы вытащить адрес обратно из int в объект IPAddress в .net, используйте метод GetBytes на BitConverter , чтобы получить int в виде байта. массив. Передайте этот массив байтов конструктору для IPAddress , который принимает массив байтов, и вы получите резервную копию с IPAddress , с которого начали.

var myIp = new IPAddress(BitConverter.GetBytes(ipAsInt));
26
ответ дан 24 November 2019 в 15:26
поделиться

Относительно этого комментария в принятом ответе

их сортировка затруднительна, если вы не наберете нули.

Вот трюк для SQL Server 2008 (от Ицика Бен-Гана в этой книге )

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)

Возвращает

ip_address
-------------
2.12.4.4
2.12.4.169
131.33.2.201
131.33.2.202
131.107.2.201
18
ответ дан 24 November 2019 в 15:26
поделиться

Лучший способ (когда нет необходимости в сортировке и другом контроле IP-адресов) - сохранить его как int , сохранение его как varchar и т. Д. Будет стоить намного больше производительности, чем просто простое невинное int.

Есть свойство IPAddress.Address , но оно устарело, я не знаю почему, поскольку, если вам не нужна сортировка или контроль над классами IP, лучше всего сохранить его как целое число без знака (которое имеет максимальное значение 0xffffffff , что равно 255.255.255.255 в десятичном представлении.

Также класс IPAddress имеет конструктор, который принимает длинный аргумент.

] И, согласно визуализатору отладчика VS, этот класс IPAddress сам хранит свою внутреннюю переменную как одно число (а не массив байтов).

Подробнее об обходных путях сохранения единицы в MS SQL Server:

3
ответ дан 24 November 2019 в 15:26
поделиться

Я читаю здесь много похожих вопросов, и ни один из ответов в этом не упоминает ответ номер один в других: "Для IPv4-адресов вы можете хранить их как int unsigned и использовать функции INET_ATON() и INET_NTOA() для возврата IP-адреса из его числового значения, и наоборот." Я думаю, это то, что я собираюсь использовать в своей базе данных, если только я не решу использовать функции php, упомянутые выше.

3
ответ дан 24 November 2019 в 15:26
поделиться
Другие вопросы по тегам:

Похожие вопросы: