完善SQL二进制到IP地址字符串转换(Perfecting SQL binary to IP Address string conversion)

发布时间 2023-04-14 11:22:43作者: 剑小秀

我们使用二进制(16)字段来存储IP地址。 我们这样做,因为它可以同时拥有IPv4和IPv6地址,并且很容易与.Net IPAddress类一起使用。

但是,为了报告目的,我创建了以下SQL函数将二进制地址转换为IP地址字符串。

CREATE FUNCTION fn_ConvertBinaryIPAddressToString
(
    @binaryIP binary(16)
)
RETURNS nvarchar(39)
AS
BEGIN
    DECLARE @ipAsString nvarchar(39)

    -- Is IPv4
    IF (substring(@binaryIP, 5, 1) = 0x00)  <-- Is there a better way?
    BEGIN

        SELECT @ipAsString = CAST(CAST(substring(@binaryIP, 1, 1) AS int) AS nvarchar(3)) + '.' +
        CAST(CAST(substring(@binaryIP, 2, 1) AS int) AS nvarchar(3)) + '.' +
        CAST(CAST(substring(@binaryIP, 3, 1) AS int) AS nvarchar(3)) + '.' +
        CAST(CAST(substring(@binaryIP, 4, 1) AS int) AS nvarchar(3))

    END
    ELSE
    BEGIN
    -- Is IPv6
        -- taken and modified from http://support.microsoft.com/kb/104829
        DECLARE @i int
        DECLARE @length int
        DECLARE @hexstring char(16)

        SELECT @ipAsString = ''
        SELECT @i = 1
        SELECT @length = 16
        SELECT @hexstring = '0123456789ABCDEF'

        WHILE (@i <= @length)
        BEGIN
            DECLARE @tempint int
            DECLARE @firstint int
            DECLARE @secondint int

            SELECT @tempint = convert(int, substring(@binaryIP,@i,1))
            SELECT @firstint = floor(@tempint/16)
            SELECT @secondint = @tempint - (@firstint*16)

            SELECT @ipAsString = @ipAsString + substring(@hexstring, @firstint+1, 1) + substring(@hexstring, @secondint+1, 1)

            IF (@i % 2 = 0)
                SELECT @ipAsString = @ipAsString + ':'

            SELECT @i = @i + 1
       END
    END

    -- Return the result of the function
    RETURN @ipAsString

END
GO

 

此刻如果5字节是0,我认为它是一个IPv4地址。 这是一个安全的假设吗? 检查所有剩余字节为零还是有更好的方法更好?

编辑删除不必要的演员


We use a binary(16) field to store IP Addresses. We do this as it can hold both IPv4 and IPv6 addresses and is easily used with the .Net IPAddress class.

However I have created the following SQL function to convert the binary address to the IP Address string for reporting purposes.

CREATE FUNCTION fn_ConvertBinaryIPAddressToString
(
    @binaryIP binary(16)
)
RETURNS nvarchar(39)
AS
BEGIN
    DECLARE @ipAsString nvarchar(39)

    -- Is IPv4
    IF (substring(@binaryIP, 5, 1) = 0x00)  <-- Is there a better way?
    BEGIN

        SELECT @ipAsString = CAST(CAST(substring(@binaryIP, 1, 1) AS int) AS nvarchar(3)) + '.' +
        CAST(CAST(substring(@binaryIP, 2, 1) AS int) AS nvarchar(3)) + '.' +
        CAST(CAST(substring(@binaryIP, 3, 1) AS int) AS nvarchar(3)) + '.' +
        CAST(CAST(substring(@binaryIP, 4, 1) AS int) AS nvarchar(3))

    END
    ELSE
    BEGIN
    -- Is IPv6
        -- taken and modified from http://support.microsoft.com/kb/104829
        DECLARE @i int
        DECLARE @length int
        DECLARE @hexstring char(16)

        SELECT @ipAsString = ''
        SELECT @i = 1
        SELECT @length = 16
        SELECT @hexstring = '0123456789ABCDEF'

        WHILE (@i <= @length)
        BEGIN
            DECLARE @tempint int
            DECLARE @firstint int
            DECLARE @secondint int

            SELECT @tempint = convert(int, substring(@binaryIP,@i,1))
            SELECT @firstint = floor(@tempint/16)
            SELECT @secondint = @tempint - (@firstint*16)

            SELECT @ipAsString = @ipAsString + substring(@hexstring, @firstint+1, 1) + substring(@hexstring, @secondint+1, 1)

            IF (@i % 2 = 0)
                SELECT @ipAsString = @ipAsString + ':'

            SELECT @i = @i + 1
       END
    END

    -- Return the result of the function
    RETURN @ipAsString

END

 


GO

At the moment if the 5 byte is 0 I assume it is an IPv4 address. Is this a safe assumption? Is it better to check all the remaining bytes for zeros or is there a better way?

EDIT removed unnecessary cast