Respostas:
Não armazene como uma string. Use uma int unsigned
coluna e armazene / recupere com INET_ATON()
e INET_NTOA()
respectivamente. O AFAIK mysql não suporta INET_ * para ipv6.
EDITAR conforme comentário
O uso da função incorporada para converter IPs para / de números inteiros (e assim armazenar esses números inteiros no banco de dados) tem o efeito colateral de validar automaticamente esses IPs. Digamos que você armazene um IP como um VARCHAR (16), certifique-se de não armazenar IPs inválidos (como 999.999.999.999 como exemplo) com alguma validação personalizada. As funções INET_ * cuidam disso.
Provavelmente é hora de começar a considerar o IPv6. O MySQL não possui métodos para converter endereços IPv6 em formato binário. Uma cadeia de quarenta caracteres manipula qualquer endereço IPv6 normal. Existe um formato que pode exceder 40 caracteres, eu consideraria improvável que ocorram práticas.
Você pode calcular o tamanho a partir das informações de que haverá no máximo 8 grupos de quatro caracteres com 7 caracteres separadores. O formato anormal substitui os dois últimos grupos por um endereço de formato IPv4. Sem compressão de endereço, ele substitui os últimos 9 caracteres por até 15 caracteres.
Se você estiver armazenando blocos, a indicação do tamanho do bloco poderá ter 4 caracteres em vez dos 3 caracteres necessários para o IPv4.
Você deve garantir que a formatação recebida seja consistente, mas todo o software que eu vi fornece formatos consistentes para os endereços.
Eu sugeriria a migração para o PostgreSQL e o uso dos tipos de dados INET ou 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
Aqui está a melhor resposta feita em uma das listas de discussão do MySQL. Leia Melhor FieldType para armazenar o endereço IP ... .
Resumidamente, sugere, o que eu segundo, para usar INT (10) UNSIGNED.
Então, usando 192.168.10.50:
(192 * 2 ^ 24) + (168 * 2 ^ 16) + (10 * 2 ^ 8) + 50 = 3232238130 (resulta em 192.168.10.50)
No MySQL, você pode usar diretamente
SELECT INET_ATON('192.168.10.50');
para obter3232238130
.
Ou
192 + (168 * 2 ^ 8) + (10 * 2 ^ 16) + (50 * 2 ^ 24) = 839559360 (Para trás, resulta em 50.10.168.192)
No MySQL, você pode usar diretamente
SELECT INET_NTOA(3232238130);
para192.168.10.50
voltar.
A partir do MySQL v5.6.3, eles adicionaram suporte INET6_ATON
e INET6_NOTA
cuidam dos endereços IPv4 e IPv6. Mas eles não o armazenam mais como um número inteiro. IPv6 retorna ae varbinary(16)
IPv4 retorna a varbinary(4)
.
http://dev.mysql.com/doc/refman/5.6/en/misc Miscellaneous-functions.html#function_inet6-aton
Você pode armazenar até 15 caracteres. Por favor, não use VARCHAR (15) porque são 16 bytes (o primeiro byte gerencia o comprimento da string e, portanto, a recuperação e o armazenamento mais lentos). Use CHAR (15) sempre em algo como um endereço IP.
Desculpe, não posso comentar as respostas. Há uma pergunta sobre isso no stackoverflow. E eu concordo totalmente com a resposta selecionada: o uso do 2xBIGINT é provavelmente o melhor caminho para o ipv6 atualmente.
Eu sugiro ir para 2 * BIGINT, mas verifique se eles não estão assinados. Existe uma espécie de divisão natural no limite de endereço / 64 no IPv6 (já que um / 64 é o menor tamanho de bloco de rede) que se alinharia muito bem com isso.
Também é possível armazenar o ipv4 nesses bigints - marcando um deles como NULL ou usando o formato V4COMPAT