2013-08-03 5 views
2

Я использую MySQL 5.6, экспериментируя с новыми функциями, такими как INET6_ATON и IS_IPV6. Когда скрипт читает IPV4, он отлично вставляет данные в таблицу. Но когда дело доходит до IPv6, одна из строк (ipTo) терпит неудачу, хотя INET6_ATON работает в одиночку.Возврат null при использовании INET6_ATON в LOAD DATA LOCAL INFILE

Мой Стол: 4 fileds

`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 их не конвертирует.

ответ

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 вместо условно переключения между INET_ATON и INET6_ATON. Последний работает отлично с IPV4 и IPV6.

Это сказанное ваш запрос может выглядеть следующим образом (при условии, что у вас нет лишних пробелов в файле 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> select geoIPID, HEX(ipfrom), HEX(ipto) from ipv6; 
+---------+----------------------------------+----------------------------------+ 
| geoIPID | HEX(ipfrom)      | HEX(ipto)      | 
+---------+----------------------------------+----------------------------------+ 
|  1 | 20010200000000000000000000000000 | 20010200FFFFFFFFFFFFFFFFFFFFFFFF | 
|  2 | 20010208000000000000000000000000 | 20010208FFFFFFFFFFFFFFFFFFFFFFFF | 
|  3 | 20010218000000000000000000000000 | 20010218FFFFFFFFFFFFFFFFFFFFFFFF | 
|  4 | 01000000       | 010000FF       | 
|  5 | 01000100       | 010003FF       | 
|  6 | 01000400       | 010007FF       | 
+---------+----------------------------------+----------------------------------+ 
6 rows in set (0.00 sec) 

mysql> select geoIPID, INET6_NTOA(ipfrom), INET6_NTOA(ipto) from ipv6; 
+---------+--------------------+----------------------------------------+ 
| geoIPID | 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 rows in set (0.00 sec)