Sqlserver
 sql >> Base de Dados >  >> RDS >> Sqlserver

Tipo de dados para armazenar o endereço IP no SQL Server


A maneira tecnicamente correta de armazenar IPv4 é binária(4), já que é o que realmente é (não, nem mesmo um INT32/INT(4), a forma textual numérica que todos conhecemos e amamos (255.255.255.255) sendo apenas a conversão de exibição de seu conteúdo binário).

Se você fizer dessa maneira, você desejará que as funções sejam convertidas de e para o formato de exibição textual:

Veja como converter o formulário de exibição textual em binário:
CREATE FUNCTION dbo.fnBinaryIPv4(@ip AS VARCHAR(15)) RETURNS BINARY(4)
AS
BEGIN
    DECLARE @bin AS BINARY(4)

    SELECT @bin = CAST( CAST( PARSENAME( @ip, 4 ) AS INTEGER) AS BINARY(1))
                + CAST( CAST( PARSENAME( @ip, 3 ) AS INTEGER) AS BINARY(1))
                + CAST( CAST( PARSENAME( @ip, 2 ) AS INTEGER) AS BINARY(1))
                + CAST( CAST( PARSENAME( @ip, 1 ) AS INTEGER) AS BINARY(1))

    RETURN @bin
END
go

E aqui está como converter o binário de volta para o formato de exibição textual:
CREATE FUNCTION dbo.fnDisplayIPv4(@ip AS BINARY(4)) RETURNS VARCHAR(15)
AS
BEGIN
    DECLARE @str AS VARCHAR(15) 

    SELECT @str = CAST( CAST( SUBSTRING( @ip, 1, 1) AS INTEGER) AS VARCHAR(3) ) + '.'
                + CAST( CAST( SUBSTRING( @ip, 2, 1) AS INTEGER) AS VARCHAR(3) ) + '.'
                + CAST( CAST( SUBSTRING( @ip, 3, 1) AS INTEGER) AS VARCHAR(3) ) + '.'
                + CAST( CAST( SUBSTRING( @ip, 4, 1) AS INTEGER) AS VARCHAR(3) );

    RETURN @str
END;
go

Aqui está uma demonstração de como usá-los:
SELECT dbo.fnBinaryIPv4('192.65.68.201')
--should return 0xC04144C9
go

SELECT dbo.fnDisplayIPv4( 0xC04144C9 )
-- should return '192.65.68.201'
go

Por fim, ao fazer pesquisas e comparações, sempre use a forma binária se quiser aproveitar seus índices.

ATUALIZAR:

Eu queria adicionar que uma maneira de resolver os problemas de desempenho inerentes de UDFs escalares no SQL Server, mas ainda manter a reutilização de código de uma função é usar um iTVF (função com valor de tabela em linha). Veja como a primeira função acima (string para binário) pode ser reescrita como um iTVF:
CREATE FUNCTION dbo.itvfBinaryIPv4(@ip AS VARCHAR(15)) RETURNS TABLE
AS RETURN (
    SELECT CAST(
               CAST( CAST( PARSENAME( @ip, 4 ) AS INTEGER) AS BINARY(1))
            +  CAST( CAST( PARSENAME( @ip, 3 ) AS INTEGER) AS BINARY(1))
            +  CAST( CAST( PARSENAME( @ip, 2 ) AS INTEGER) AS BINARY(1))
            +  CAST( CAST( PARSENAME( @ip, 1 ) AS INTEGER) AS BINARY(1))
                AS BINARY(4)) As bin
        )
go

Aqui está no exemplo:
SELECT bin FROM dbo.fnBinaryIPv4('192.65.68.201')
--should return 0xC04144C9
go

E aqui está como você usaria em um INSERT
INSERT INTo myIpTable
SELECT {other_column_values,...},
       (SELECT bin FROM dbo.itvfBinaryIPv4('192.65.68.201'))