Ответы:
Не хранить в виде строки. Используйте int unsigned
столбец и сохраните / получите с INET_ATON()
и INET_NTOA()
соответственно. AFAIK mysql не поддерживает INET_ * для ipv6.
РЕДАКТИРОВАТЬ согласно комментарию
Использование встроенной функции для преобразования IP-адресов в целые числа и из них (и, таким образом, сохранение этих целых чисел в базе данных) имеет побочный эффект автоматической проверки этих IP-адресов. Скажем, вы храните IP-адрес как VARCHAR (16), вы должны убедиться, что не сохранили недопустимые IP-адреса (например, 999.999.999.999) с некоторой пользовательской проверкой. Функции INET_ * позаботятся об этом.
Вероятно, пришло время начать рассматривать IPv6. MySQL не имеет методов для преобразования адресов IPv6 в двоичный формат. Строка из сорока символов будет обрабатывать любые обычные адреса IPv6. Существует формат, который может превышать 40 символов, я бы посчитал, что это вряд ли произойдет на практике.
Вы можете рассчитать размер на основе информации о том, что будет не более 8 четырехсимвольных групп с 7 символами-разделителями. Ненормальный формат заменяет две последние группы адресом формата IPv4. Без сжатия адреса он заменяет последние 9 символов до 15 символов.
Если вы храните блоки, для указания размера блока может потребоваться 4 символа, а не 3 символа, требуемые для IPv4.
Вы должны убедиться, что форматирование, которое вы получаете, является согласованным, но все программное обеспечение, которое я видел, предоставляет согласованные форматы для адресов.
Я бы предложил перейти на PostgreSQL и использовать типы данных INET или 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
Вот лучший ответ, сделанный в одном из списков рассылки MySQL. Read Best FieldType для хранения IP - адрес ... .
Вкратце он предлагает, во-вторых, использовать INT (10) UNSIGNED.
Итак, используя 192.168.10.50:
(192 * 2 ^ 24) + (168 * 2 ^ 16) + (10 * 2 ^ 8) + 50 = 3232238130 (результат 192.168.10.50)
В MySQL вы можете напрямую использовать
SELECT INET_ATON('192.168.10.50');
для получения3232238130
.
Или
192 + (168 * 2 ^ 8) + (10 * 2 ^ 16) + (50 * 2 ^ 24) = 839559360 (в обратном порядке результат 50.10.168.192)
В MySQL вы можете напрямую использовать,
SELECT INET_NTOA(3232238130);
чтобы192.168.10.50
вернуться.
По MySQL v5.6.3 они добавили поддержку INET6_ATON
и INET6_NOTA
что будет заботиться о IPv4 и IPv6. Но они больше не хранят его как целое число. IPv6 возвращает a varbinary(16)
и IPv4 возвращает a varbinary(4)
.
http://dev.mysql.com/doc/refman/5.6/en/miscellaneous-functions.html#function_inet6-aton
Вы можете хранить до 15 символов. Пожалуйста, не используйте VARCHAR (15), потому что это 16 байтов (первый байт управляет длиной строки и, следовательно, медленнее извлекает и хранит). Используйте CHAR (15) всегда на чем-то вроде IP-адреса.
Извините, не могу комментировать ответы. Есть вопрос об этом на stackoverflow. И я полностью согласен с выбранным ответом: использование 2xBIGINT, вероятно, является лучшим способом для ipv6 в настоящее время.
Я бы предложил 2 * BIGINT, но убедитесь, что они НЕ ПОДПИСАНЫ. На границе адреса / 64 в IPv6 существует своего рода естественное разделение (так как / 64 - это наименьший размер сетевого блока), которое хорошо согласуется с этим.
Также можно хранить ipv4 на этих bigints - либо пометив один из них как NULL, либо используя формат V4COMPAT