Sqlserver
 sql >> Datenbank >  >> RDS >> Sqlserver

Datentyp zum Speichern der IP-Adresse in SQL Server

Die technisch korrekte Art, IPv4 zu speichern, ist binär(4), da es das tatsächlich ist (nein, nicht einmal ein INT32/INT(4), wobei die numerische Textform, die wir alle kennen und lieben (255.255.255.255), gerecht ist die Anzeigeumwandlung seines binären Inhalts).

Wenn Sie dies auf diese Weise tun, möchten Sie, dass Funktionen in das und aus dem Textanzeigeformat konvertieren:

So konvertieren Sie die textuelle Anzeigeform in eine binäre:

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

Und so konvertieren Sie die Binärdatei zurück in die Textanzeigeform:

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

Hier ist eine Demo, wie man sie benutzt:

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

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

Schließlich sollten Sie beim Suchen und Vergleichen immer die binäre Form verwenden, wenn Sie Ihre Indizes nutzen möchten.

UPDATE:

Ich wollte hinzufügen, dass eine Möglichkeit, die inhärenten Leistungsprobleme von skalaren UDFs in SQL Server anzugehen, aber dennoch die Codewiederverwendung einer Funktion beizubehalten, darin besteht, stattdessen eine iTVF (Inline-Tabellenwertfunktion) zu verwenden. So kann die erste obige Funktion (String zu Binär) als iTVF umgeschrieben werden:

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

Hier ist es im Beispiel:

SELECT bin FROM dbo.fnBinaryIPv4('192.65.68.201')
--should return 0xC04144C9
go

Und so würden Sie es in einem INSERT verwenden

INSERT INTo myIpTable
SELECT {other_column_values,...},
       (SELECT bin FROM dbo.itvfBinaryIPv4('192.65.68.201'))