我有以下IP地址(示例):195.65.254.11
我希望构建一组查询(或函数)来返回此IP所属的网络(195.65.254.0/24
)
我首先将IP转换为整数:
create function [dbo].[IPAddressToInteger] (@IP as varchar(15))
returns bigint
as
begin
return (convert(bigint, parsename(@IP,1)) +
convert(bigint, parsename(@IP,2)) * 256 +
convert(bigint, parsename(@IP,3)) * 256 * 256 +
convert(bigint, parsename(@IP,4)) * 256 * 256 * 256)
end
select dbo.IPAddressToInteger('195.65.254.11'); -- 3275881995
然后我计算了CIDR:
create function [dbo].[CIDRFromMask] (@mask as bigint)
returns varchar(5)
as
begin
declare @maskCalc bigint
select @maskCalc = dbo.IPAddressToInteger('255.255.255.255') - @mask + 1
declare @logCalc int
select @logCalc = (32 - log(@maskCalc, 2))
return '/' + cast(@logCalc as varchar(5))
end
select dbo.CIDRFromMask('3275881995'); -- /2
但在这里我被困住了。如何继续检索正确的网络?
答案 0 :(得分:0)
如果您有网络表,请将开始和停止范围存储为列。例如:
Network Start Stop Name
1.0.0.0/24 1.0.0.0 1.0.0.255 Some guy
(实际上,Start
和Stop
将存储为整数,但对于此示例,我显示的是点分四维)
要查询地址所属的网络,请使用BETWEEN
:
SELECT n.Network, n.Name
FROM Networks n
WHERE @TargetAddress BETWEEN n.Start and n.Stop
(同样,根据需要插入IPAddressToInteger
的调用)
要从网络地址和掩码生成Start
和Stop
值,请使用以下公式。
Start = Network Address
Stop = Network Address | (~Subnet Mask)
在假设没有全局可路由网络将使用长度超过64位的前缀(我认为是这种情况,但我目前懒得验证)的情况下,使用64位整数可以在这种设计中简单地容纳IPv6。 / p>
将BETWEEN
与Start
和Stop
一起使用的优势在于查询能够利用您创建的索引,与使用{{1 }}