Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Perfecting SQL binary to IP Address string conversion

Tags:

sql

sql-server

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

like image 837
Magpie Avatar asked Sep 08 '10 08:09

Magpie


People also ask

What is binary string in SQL?

A binary string is a sequence of bytes. Unlike a character string which usually contains text data, a binary string is used to hold non-traditional data such as pictures. The length of a binary string is the number of bytes in the sequence. A binary string has a CCSID of 65535.

Can we convert int to string in SQL?

The CONCAT implicitly converts values into strings. If you need to concatenate different data types, CONCAT is the best option instead of using the + character. Note: If you need to convert int into a string to compare, the cast and convert should be used.

Can you change the IP address of a SQL Server?

On the right pane, under the Server Name category, right-click the SQL Server Instance, and select Properties option to open the Properties dialog box. On the General tab, change the IP address resource.

What is data type for IP address in SQL Server?

As with MS SQL Server you can store IP address, both IPv4 and IPv6, either as varchar or as numeric. As already mentioned, the binary representation is much more preferable than any other as it reflects the true nature of an IP address.


1 Answers

I'd say you ought to be storing the address family also, either encoded in your byte array or as a separate column. If you pass 16 bytes to the IPAddress constructor, it will construct as IPv6 address, so you'd need checks in your code also to determine the address family. It would seem a lot easier (and not rely on assumptions about the bytes of an IPv6 address) to keep this information around directly.

Or use a varbinary(16), which you can then check the length of (length=4 => IPv4 address)

like image 138
Damien_The_Unbeliever Avatar answered Sep 18 '22 09:09

Damien_The_Unbeliever