MaxMind的GeoLite2是一个很棒的数据库,如果你想将IP地址映射到国家,它非常有用.
为了有效地做到这一点,我想用这样的方案将它导入MySQL数据库:
我记得很久以前为CSV数据库编写了一个导入脚本,但是今天可以下载的CSV格式很难理解,至少对我来说是这样的:
network,geoname_id,registered_country_geoname_id,represented_country_geoname_id,is_anonymous_proxy,is_satellite_provider
1.0.0.0/24,2077456,2077456,,0,0
1.0.1.0/24,1814991,1814991,,0,0
1.0.2.0/23,1814991,1814991,,0,0
1.0.4.0/22,2077456,2077456,,0,0
1.0.8.0/21,1814991,1814991,,0,0
1.0.16.0/20,1861060,1861060,,0,0
1.0.32.0/19,1814991,1814991,,0,0
1.0.64.0/18,1861060,1861060,,0,0
1.0.128.0/17,1605651,1605651,,0,0
我真的很喜欢这里的基础知识.将数据库从CSV表示导入MySQL的最有效和最简单的方法是什么?
解决方法:
network,geoname_id,registered_country_geoname_id,represented_country_geoname_id,is_anonymous_proxy,is_satellite_provider
1.0.0.0/24,2077456,2077456,,0,0
1.0.1.0/24,1814991,1814991,,0,0
1.0.2.0/23,1814991,1814991,,0,0
1.0.4.0/22,2077456,2077456,,0,0
create table thing1
( network varchar(20) not null,
geoname_id varchar(20) not null,
registered_country_geoname_id varchar(20) not null,
represented_country_geoname_id varchar(20) not null,
is_anonymous_proxy varchar(20) not null,
is_satellite_provider varchar(20) not null
);
LOAD DATA INFILE 'c:\\dev\\ipaddr.txt'
INTO TABLE thing1
FIELDS TERMINATED BY ','
LINES TERMINATED BY '\n'
IGNORE 1 LINES
(@v1,@v2,@v3,@v4,@v5,@v6)
set network=ifnull(@v1,''),
geoname_id=ifnull(@v2,''),
registered_country_geoname_id=ifnull(@v3,''),
represented_country_geoname_id=ifnull(@v4,''),
is_anonymous_proxy=ifnull(@v5,''),
is_satellite_provider=ifnull(@v6,'');
以上对我来说很好.
下面的编辑开始
对于下面的内容,尝试在评论中的stijn-de-witt点之后改进此答案.
但请注意,注释中引用的博客在更新语句中有一个错误,用于进入int.因此,直到我解决这个问题,我发现了varchar修改,如下所示.
编辑1(更多内容如下,请参阅下面的评论答案):
Alter the table to get a "from ip to ip range"
alter table thing1 add column from_ip varchar(20), add column to_ip varchar(20);
-- note that those two are nullable at the moment. You can always change that later
刚添加的varchar的更新表
update thing1
set from_ip= INET_NTOA(INET_ATON( SUBSTRING_INDEX(network, '/', 1))
& 0xffffffff ^ ((0x1 << ( 32 - SUBSTRING_INDEX(network, '/', -1)) ) -1 )),
to_ip= INET_NTOA(INET_ATON( SUBSTRING_INDEX(network, '/', 1))
| ((0x100000000 >> SUBSTRING_INDEX(network, '/', -1) ) -1 ))
select * from thing1;
(对于上述更新声明,在此answer中归功于Bernd Buffen)
以上更新声明的结果:
mysql> select network,from_ip,to_ip from thing1;
+------------+---------+-----------+
| network | from_ip | to_ip |
+------------+---------+-----------+
| 1.0.1.0/24 | 1.0.1.0 | 1.0.1.255 |
| 1.0.2.0/23 | 1.0.2.0 | 1.0.3.255 |
| 1.0.4.0/22 | 1.0.4.0 | 1.0.7.255 |
+------------+---------+-----------+
从这里,查看针对INET_ATON(expr)的MySQL手册第Miscellaneous Functions页.
Edit2(再次感谢stijn-de-witt):
alter table thing1 add column uint_from_ip int unsigned, add column uint_to_ip int unsigned;
UPDATE thing1 SET uint_from_ip = inet_aton(SUBSTRING(network, 1, LOCATE('/', network) - 1)),
uint_to_ip = (inet_aton(SUBSTRING(network, 1, LOCATE('/', network) - 1)) + (pow(2, (32-CONVERT(SUBSTRING(network, LOCATE('/', network) + 1), UNSIGNED INT)))-1));
结果:
select network,from_ip,to_ip,uint_from_ip,uint_to_ip from thing1;
+------------+---------+-----------+--------------+------------+
| network | from_ip | to_ip | uint_from_ip | uint_to_ip |
+------------+---------+-----------+--------------+------------+
| 1.0.1.0/24 | 1.0.1.0 | 1.0.1.255 | 16777472 | 16777727 |
| 1.0.2.0/23 | 1.0.2.0 | 1.0.3.255 | 16777728 | 16778239 |
| 1.0.4.0/22 | 1.0.4.0 | 1.0.7.255 | 16778240 | 16779263 |
+------------+---------+-----------+--------------+------------+
(经过一些修复后提到的上述信用额度为S0BEIT blog)