查找IP地址块表中的间隙

时间:2014-09-25 21:25:37

标签: sql sql-server tsql sql-server-2005

我有一个表,其中包含 SQL Server 2005 中的以下字段和示例数据: id block block_start block_end size 523 10.211.15.16/28 0x0AD30F10 0x0AD30F1F 16 531 10.211.15.36/30 0x0AD30F24 0x0AD30F27 4 532 10.211.15.40/29 0x0AD30F28 0x0AD30F2F 8 533 10.211.15.48/29 0x0AD30F30 0x0AD30F37 8 525 10.211.15.72/29 0x0AD30F48 0x0AD30F4F 8

id是INT标识列。 block是VARCHAR(18),表示CIDR格式的IP块。 block_start和block_end分别是BINARY(4),分别表示块中的第一个和最后一个IPv4地址。大小是块中的IP地址数。

在给定范围的IP和IP数量作为输入的情况下,我需要一种方法来查询第一个可用间隙。例如,我可能希望在 10.211.15.16 10.211.15.80 之间找到 4 IP地址的第一个缺失缺口。在此示例中,正确的输出应为10.211.15.32/30(0x0AD30F20至0x0AD30F23)。如果我希望 8 IP地址的第一个间隙在同一范围内,则正确的输出应为10.211.15.56/29(0x0AD30F38到0x0AD30F3F)。

输出为CIDR(varchar)或二进制格式不是问题,因为我有可以在两者之间轻松转换的函数,但我想要查询需要对二进制字段进行。

如果有必要,我可以利用应用程序逻辑(Java或ColdFusion),但如果我能帮助它,我宁愿不这样做。

添加了sqlfiddle:http://sqlfiddle.com/#!3/d45ad

1 个答案:

答案 0 :(得分:2)

您可以使用lead()并将块字段转换为整数来找到差距。像这样:

select t.*
from (select t.*,
             cast(lead(block_start) over (order by block_start) as bigint) as nextstart,
             cast(block_end as bigint) as thisend
      from iptable t
     ) t
where nextstart - thisend - 1 > @MYNUMBEROFIPS;

如果你想在块上使用范围比较,那就要非常小心。在进行比较之前,您应该将块转换为数值。

编辑:

您可以通过执行以下操作获得等效功能:

select t.*
from (select t.*, cast(block_end as bigint) as thisend,
             (select top 1 cast(block_start as bigint)
              from iptable t2
              where t2.block_start > t.block_start
              order by t2.block_start
             ) as nextstart
      from iptable t
     ) t
where nextstart - thisend - 1 > @MYNUMBEROFIPS;