Select record between two IP ranges

前端 未结 8 2134
遇见更好的自我
遇见更好的自我 2021-02-19 05:14

I have a table which stores a ID, Name, Code, IPLow, IPHigh such as:

1, Lucas, 804645, 192.130.1         


        
8条回答
  •  死守一世寂寞
    2021-02-19 05:24

    Consider something like this example to convert the address into a number.

    CREATE FUNCTION dbo.IPAddressAsNumber (@IPAddress AS varchar(15))
    RETURNS bigint
    BEGIN
    RETURN
     CONVERT (bigint,
      CONVERT(varbinary(1), CONVERT(int, PARSENAME(@IPAddress, 4))) +
      CONVERT(varbinary(1), CONVERT(int, PARSENAME(@IPAddress, 3))) +
      CONVERT(varbinary(1), CONVERT(int, PARSENAME(@IPAddress, 2))) +
      CONVERT(varbinary(1), CONVERT(int, PARSENAME(@IPAddress, 1))) )
    END
    

    and with that you could use standard operators like BETWEEN to find rows within the range you have in the table

    DECLARE @t table (ID int, Name varchar(50), Code int, IPLow varchar(15), IPHigh varchar(15))
    INSERT INTO @t VALUES 
     (1, 'Lucas', 804645, '192.130.1.1', '192.130.1.254'),
     (2, 'Maria', 222255, '192.168.2.1', '192.168.2.254'),
     (3, 'Julia', 123456, '192.150.3.1', '192.150.3.254')
    
    SELECT * FROM @t
    WHERE dbo.IPAddressAsNumber('192.168.2.50')
     BETWEEN dbo.IPAddressAsNumber(IPLow) AND dbo.IPAddressAsNumber(IPHigh)
    

    The scheme essentially uses PARSENAME to isolate each part of the address, converts each part into a SQL binary string, concatenating the strings together to get a single SQL binary string representing the address, and shows the result as a bigint.

    In a textual representation of hexadecimal values think of this as smashing the 4 parts together 192(0xC0) + 168(0xA8) + 2(0x02) + 50(0x32) into 0xC0A80232. When you turn that combined string into its binary digits (0s and 1s) you would end up with something that could be thought of as the address in a binary form used by the network stack in address routing and subnet masking tables. When you turn that into a number in the form of an unsigned integer (or in this case a bigint) you get 3232236082.

    Interestingly this scheme gives you a "number" that can be used in place of the original address in lots of ways. You can for example ping the number 2130706433 instead of the address 127.0.0.1 -- the name resolver in Windows will convert it similarly to how DNS is used to find the address of a hostname.

    For the sake of completeness, here is another function that can be used to convert the number form back into the standard string form

    CREATE FUNCTION dbo.IPAddressFromNumber (@IPNumber AS bigint)
    RETURNS varchar(15)
    BEGIN
    RETURN
     CONVERT (varchar(15),
      CONVERT(varchar(3), CONVERT(int, SUBSTRING(CONVERT(varbinary(4), @IPNumber), 1,1))) + '.' +
      CONVERT(varchar(3), CONVERT(int, SUBSTRING(CONVERT(varbinary(4), @IPNumber), 2,1))) + '.' +
      CONVERT(varchar(3), CONVERT(int, SUBSTRING(CONVERT(varbinary(4), @IPNumber), 3,1))) + '.' +
      CONVERT(varchar(3), CONVERT(int, SUBSTRING(CONVERT(varbinary(4), @IPNumber), 4,1))) )
    END
    

提交回复
热议问题