2

我正在使用 MySQL 5.6,尝试新功能,例如INET6_ATONIS_IPV6. 当脚本读取IPV4时,它将数据完美地插入到表中。但是当涉及到 时IPv6,其中一行(ipTo)失败了,即使INET6_ATON单独工作也是如此。

我的表:4 个文件

`geoIPID` INT NOT NULL AUTO_INCREMENT ,
`IPFrom` VARBINARY(16) NOT NULL ,
`IPTo` VARBINARY(16) NOT NULL ,
`countries_countryID` INT NOT NULL

将文本文件加载到表中的脚本:

LOAD DATA LOCAL INFILE '/Users/Invictus/Documents/htdocs/overkill/etcs/IPV6.csv' 
INTO TABLE `overkill`.`geoIP` 
   FIELDS TERMINATED BY ',' ENCLOSED BY '"' 
   LINES TERMINATED BY '\n' 
(@IPFrom, @IPTo, @dummy, @dummy, @countryAbbreviation, @dummy) 
SET IPFrom = IF(IS_IPV4(@IPFrom), 
                 INET_ATON(@IPFrom), 
                 INET6_ATON(@IPFrom)), 
    IPTo = IF(IS_IPV4(@IPTo), 
              INET_ATON(@IPTo), 
              INET6_ATON(@IPTo)), 
    countries_countryID = 
    (
      SELECT IF (COUNT(*) != 0, `countries`.`countryID`, 999) 
        FROM `countries` 
       WHERE `countries`.`countryAbbreviation` = @countryAbbreviation 
       LIMIT 1
    );

IPV4.csv 文件,如下所示:

"1.0.0.0","1.0.0.255","16777216","16777471","AU","Australia"
"1.0.1.0","1.0.3.255","16777472","16778239","CN","China"
"1.0.4.0","1.0.7.255","16778240","16779263","AU","Australia"

IPV6.csv 文件,如下所示:

"2001:200::", "2001:200:ffff:ffff:ffff:ffff:ffff:ffff", "42540528726795050063891204319802818560", "42540528806023212578155541913346768895", "JP", "Japan"
"2001:208::", "2001:208:ffff:ffff:ffff:ffff:ffff:ffff", "42540529360620350178005905068154421248", "42540529439848512692270242661698371583", "SG", "Singapore"
"2001:218::", "2001:218:ffff:ffff:ffff:ffff:ffff:ffff", "42540530628270950406235306564857626624", "42540530707499112920499644158401576959", "JP", "Japan"

我的问题:

如果我加载IPv6,第二行(ipTo)NULL。为什么?文件中的所有值都是有效的,但 MySQL 不会转换它们。

4

1 回答 1

2

问题不在您的文件中,INET6_ATON而是在您的IPV6.csv文件中。不像IPV4.csv你在逗号后面有额外的空格,这会让LOAD DATA你像这样阅读你的第二个字段

 "2001:200:ffff:ffff:ffff:ffff:ffff:ffff" 
^^                                      ^

这就是为什么INET6_ATON返回NULL

要解决这个问题:

  1. 删除 csv 文件中的多余空格
  2. 或将分隔符更改为FIELDS TERMINATED BY ', '

此外,您可以简化查询,只需使用而不是有条件地在和INET6_ATON之间切换。后者适用于 IPV4 和 IPV6。INET_ATONINET6_ATON

话虽如此,您的查询可能看起来像这样(假设您在 csv 文件中没有多余的空格

LOAD DATA LOCAL INFILE '/Users/Invictus/Documents/htdocs/overkill/etcs/IPV6.csv' 
INTO TABLE `overkill`.`geoIP` 
   FIELDS TERMINATED BY ',' ENCLOSED BY '"' 
   LINES TERMINATED BY '\n' 
(@ipfrom, @ipto, @dummy, @dummy, @abbr, @dummy) 
SET IPFrom = INET6_ATON(@ipfrom), 
    IPTo   = INET6_ATON(@ipto), 
    countries_countryID = 
    (
      SELECT IF(COUNT(*) != 0, `countries`.`countryID`, 999) 
        FROM `countries` 
       WHERE `countries`.`countryAbbreviation` = @abbr 
       LIMIT 1
    );

为了测试,我删除了多余的空格,合并了你的两个文件,并将它们加载到ipv6表中。这是结果

mysql> 从 ipv6 中选择 geoIPID、HEX(ipfrom)、HEX(ipto);
+---------+----------------------------------+---- ------------------------------+
| 地理IPID | 十六进制(ipfrom) | 十六进制(ipto) |
+---------+----------------------------------+---- ------------------------------+
| 1 | 20010200000000000000000000000000 | 20010200FFFFFFFFFFFFFFFFFFFFFFFF |
| 2 | 200102080000000000000000000000000 | 20010208FFFFFFFFFFFFFFFFFFFFFFFF |
| 3 | 200102180000000000000000000000000 | 20010218FFFFFFFFFFFFFFFFFFFFFFFF |
| 4 | 01000000 | 010000FF |
| 5 | 01000100 | 010003FF |
| 6 | 01000400 | 010007FF |
+---------+----------------------------------+---- ------------------------------+
6 行一组(0.00 秒)

mysql> 从 ipv6 中选择 geoIPID、INET6_NTOA(ipfrom)、INET6_NTOA(ipto);
+---------+--------------------+------------------ ----------------------+
| 地理IPID | INET6_NTOA(ipfrom) | INET6_NTOA(ipto) |
+---------+--------------------+------------------ ----------------------+
| 1 | 2001:200:: | 2001:200:ffff:ffff:ffff:ffff:ffff:ffff |
| 2 | 2001:208:: | 2001:208:ffff:ffff:ffff:ffff:ffff:ffff |
| 3 | 2001:218:: | 2001:218:ffff:ffff:ffff:ffff:ffff:ffff |
| 4 | 1.0.0.0 | 1.0.0.255 |
| 5 | 1.0.1.0 | 1.0.3.255 |
| 6 | 1.0.4.0 | 1.0.7.255 |
+---------+--------------------+------------------ ----------------------+
6 行一组(0.00 秒)

于 2013-08-15T04:27:33.817 回答