Cách chính xác về mặt kỹ thuật để lưu trữ IPv4 là nhị phân (4), vì đó là thực tế (không, thậm chí không phải là INT32 / INT (4), dạng văn bản số mà tất cả chúng ta đều biết và yêu thích (255.255.255.255) chỉ là chuyển đổi hiển thị nội dung nhị phân của nó).
Nếu làm theo cách này, bạn sẽ muốn các hàm chuyển đổi sang và từ định dạng hiển thị văn bản:
Đây là cách chuyển đổi dạng hiển thị văn bản sang dạng nhị phân:
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
Và đây là cách chuyển đổi nhị phân trở lại dạng hiển thị văn bản:
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
Dưới đây là bản trình diễn về cách sử dụng chúng:
SELECT dbo.fnBinaryIPv4('192.65.68.201')
--should return 0xC04144C9
go
SELECT dbo.fnDisplayIPv4( 0xC04144C9 )
-- should return '192.65.68.201'
go
Cuối cùng, khi thực hiện tra cứu và so sánh, hãy luôn sử dụng biểu mẫu nhị phân nếu bạn muốn có thể tận dụng các chỉ mục của mình.
CẬP NHẬT:
Tôi muốn thêm rằng một cách để giải quyết các vấn đề về hiệu suất cố hữu của UDF vô hướng trong SQL Server, nhưng vẫn giữ nguyên khả năng tái sử dụng mã của một hàm là sử dụng iTVF (hàm có giá trị bảng nội tuyến). Đây là cách hàm đầu tiên ở trên (chuỗi thành nhị phân) có thể được viết lại dưới dạng 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
Đây là nó trong ví dụ:
SELECT bin FROM dbo.fnBinaryIPv4('192.65.68.201')
--should return 0xC04144C9
go
Và đây là cách bạn sẽ sử dụng nó trong INSERT
INSERT INTo myIpTable
SELECT {other_column_values,...},
(SELECT bin FROM dbo.itvfBinaryIPv4('192.65.68.201'))