Maxmind有两个免费的GeoLite2 cvs文件,我们可以用它来查找与IP地址范围相关的位置。我想在SQL Server中创建一个使用导入的表([GeoLite2_City_Blocks]和[GeoLite2_City_Locations])的存储过程,获取在IP地址中传递的varchar(45)字符串并返回与该IP地址关联的位置。我原本以为网上会有相关的T-SQL代码,但我找不到它。
我检查了Querying GeoLite2 Country CSV in SQL,但我根本不明白Prefix_Length(在Blocks表中称为Network_mask_Length),是或是。如果它们与CIDR前缀相同(请参阅:http://en.wikipedia.org/wiki/IPv6_subnetting_reference),我会更加困惑,因为Network_mask_Length可能是118,119,或维基百科页面上未显示的任何其他数字。
我已经看到一个网页在SQL Server中讨论IPv6,建议使用零进行填充以进行比较。我想不能简单地查询免费的GeoLite2而不至少在该表的最终IP地址中添加一个额外的列?
我想我可以从IPv4地址前面删除“:: ffff:”,如果这是正确的说法。但我仍然没有得到如何将network_mask_length(前缀)字段转换为我理解的内容。然后填零IPv6地址,但后来我仍然不知道该前缀是什么。
我的问题是:
答案 0 :(得分:7)
我使用此查询(实际上是它的MySQL)来导入块文件,将IP地址转换为从 - 到IP范围,以进行简单的BETWEEN
查询。
我在表格中添加了两个字段:start_ip
和end_ip
。 start_ip
填充了network_start_ip
的数值,end_ip
填充了使用network_mask_length
计算的ip范围的结尾。正如@oschwald所说,我从前缀长度减去了96并删除了:: FFFF:。
LOAD DATA LOCAL INFILE 'GeoLite2-City-Blocks.csv'
INTO TABLE geoip_blocks
COLUMNS TERMINATED BY ','
OPTIONALLY ENCLOSED BY '"'
LINES STARTING BY '::ffff:' -- import only ipv4 and cut off the ipv6 prefix
IGNORE 2 LINES
(network_start_ip, network_mask_length, geoname_id,
registered_country_geoname_id, represented_country_geoname_id, postal_code,
latitude, longitude, is_anonymous_proxy, is_satellite_provider)
SET start_ip = inet_aton(network_start_ip), -- set start ip as given
end_ip = inet_aton(network_start_ip) +
(pow(2, (32 - (network_mask_length -96))) - 1) - 1, -- calc end_ip using mask
network_mask_length = network_mask_length - 96 -- subtract 96 as we use ipv4
使用
查询数据SELECT geoname_id
FROM geoip_blocks
WHERE
INET_ATON('123.123.123.123') BETWEEN start_ip AND end_ip
LIMIT 1
答案 1 :(得分:1)
前缀长度是网络地址中的有效位数。对于任何IPv6地址,这是0-128之间的数字,因为IPv6地址的长度为128位。例如,前缀为128的网络只包含一个IP地址。前缀为127的网络将包含两个地址。 126将有4,依此类推。
表格:: FFFF:10.11.12.13的IPv6地址,如您所说,对应于删除了':: FFFF:'的IPv4地址。 ':: FFFF:'对应于地址的前96位。如果IPv6地址的前缀长度为126,则IPv4地址的前缀长度为30(即最后两位是重要的)。
Google search应显示代码段以将CIDR表示法转换为范围。如果您只关心IPv4,最简单的方法是预先过滤数据,删除:: FFFF:,从前缀长度减去96,并丢弃未映射到IPv4的地址范围。