Technicznie poprawnym sposobem przechowywania IPv4 jest binarny(4), ponieważ tak naprawdę jest (nie, nawet INT32/INT(4), numeryczna forma tekstowa, którą wszyscy znamy i kochamy (255.255.255.255) jest po prostu konwersja wyświetlania zawartości binarnej).
Jeśli zrobisz to w ten sposób, będziesz chciał, aby funkcje konwertowały do iz formatu tekstowego:
Oto jak przekonwertować tekstowy formularz wyświetlania na binarny:
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
A oto jak przekonwertować plik binarny z powrotem do postaci tekstowej:
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
Oto demonstracja, jak z nich korzystać:
SELECT dbo.fnBinaryIPv4('192.65.68.201')
--should return 0xC04144C9
go
SELECT dbo.fnDisplayIPv4( 0xC04144C9 )
-- should return '192.65.68.201'
go
Wreszcie, podczas wyszukiwania i porównywania zawsze używaj formy binarnej, jeśli chcesz mieć możliwość wykorzystania swoich indeksów.
AKTUALIZACJA:
Chciałem dodać, że jednym ze sposobów rozwiązania nieodłącznych problemów z wydajnością skalarnych funkcji UDF w SQL Server, przy jednoczesnym zachowaniu możliwości ponownego wykorzystania kodu funkcji, jest użycie iTVF (wbudowanej funkcji z wartościami tabelarycznymi). Oto jak pierwsza funkcja powyżej (ciąg na binarny) może zostać przepisana jako 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
Oto przykład:
SELECT bin FROM dbo.fnBinaryIPv4('192.65.68.201')
--should return 0xC04144C9
go
A oto jak można go użyć we WSTAWCE
INSERT INTo myIpTable
SELECT {other_column_values,...},
(SELECT bin FROM dbo.itvfBinaryIPv4('192.65.68.201'))