Select record between two IP ranges

前端 未结 8 2171
遇见更好的自我
遇见更好的自我 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:19

    I was thinking along the lines of Gordon's answer, then realized you don't actually need to mess with numbers. If you zero-pad each part of the address, a string comparison works:

    DECLARE @search varchar(50) = '192.168.2.50';
    WITH DATA AS (
        SELECT * FROM ( values 
                (1, 'Lucas', '192.130.1.1', '192.130.1.254'),
                (2, 'Maria', '192.168.2.1', '192.168.2.254'),
                (3, 'Julia', '192.150.3.1', '192.150.3.254')
        ) AS tbl (ID,Name,IPLow,IPHigh)
    )
    SELECT *
    FROM DATA
    WHERE REPLACE(STR(PARSENAME( @search, 4 ), 3, 0), ' ', '0')
        + REPLACE(STR(PARSENAME( @search, 3 ), 3, 0), ' ', '0')
        + REPLACE(STR(PARSENAME( @search, 2 ), 3, 0), ' ', '0')
        + REPLACE(STR(PARSENAME( @search, 1 ), 3, 0), ' ', '0')
    
        BETWEEN
    
          REPLACE(STR(PARSENAME( IPLow, 4 ), 3, 0), ' ', '0')
        + REPLACE(STR(PARSENAME( IPLow, 3 ), 3, 0), ' ', '0')
        + REPLACE(STR(PARSENAME( IPLow, 2 ), 3, 0), ' ', '0')
        + REPLACE(STR(PARSENAME( IPLow, 1 ), 3, 0), ' ', '0')
    
        AND
    
          REPLACE(STR(PARSENAME( IPHigh, 4 ), 3, 0), ' ', '0')
        + REPLACE(STR(PARSENAME( IPHigh, 3 ), 3, 0), ' ', '0')
        + REPLACE(STR(PARSENAME( IPHigh, 2 ), 3, 0), ' ', '0')
        + REPLACE(STR(PARSENAME( IPHigh, 1 ), 3, 0), ' ', '0')
    

    You can, of course, put this inside a UDF for simplicity, though watch out for the performance hit on large queries.

    CREATE FUNCTION dbo.IP_Comparable(@IP varchar(50))
    RETURNS varchar(50)
    WITH SCHEMABINDING
    BEGIN
        RETURN REPLACE(STR(PARSENAME( @IP, 4 ), 3, 0), ' ', '0')
             + REPLACE(STR(PARSENAME( @IP, 3 ), 3, 0), ' ', '0')
             + REPLACE(STR(PARSENAME( @IP, 2 ), 3, 0), ' ', '0')
             + REPLACE(STR(PARSENAME( @IP, 1 ), 3, 0), ' ', '0')
    END
    GO
    
    DECLARE @search varchar(50) = '192.168.2.50';
    WITH DATA AS (
        SELECT * FROM ( values 
            (1, 'Lucas', '192.130.1.1', '192.130.1.254'),
            (2, 'Maria', '192.168.2.1', '192.168.2.254'),
            (3, 'Julia', '192.150.3.1', '192.150.3.254')
        ) AS tbl (ID,Name,IPLow,IPHigh)
    )
    SELECT *
    FROM DATA
    WHERE dbo.IP_Comparable(@search) BETWEEN dbo.IP_Comparable(IPLow) AND dbo.IP_Comparable(IPHigh)
    

    This will avoid the issue you're having with integer overflows.

提交回复
热议问题