将 geonames.org 数据库中的数据导入 MySQL DB
Posted
技术标签:
【中文标题】将 geonames.org 数据库中的数据导入 MySQL DB【英文标题】:Importing data from geonames.org database into MySQL DB 【发布时间】:2011-07-14 07:16:57 【问题描述】:有人如何将 geonames.org 数据导入我的数据库吗?我要导入的是http://download.geonames.org/export/dump/DO.zip,我的数据库是一个 mysql 数据库。
【问题讨论】:
您是否尝试导入 zip ?如果不是什么是文件结构? 【参考方案1】:这是我导入成功后的笔记。
在撰写本文时,我正在 Windows 7 上使用 MySQL 5.7.16 进行测试。按照以下步骤导入:
从official download page 下载所需的数据文件。在我的例子中,我选择了 cities1000.zip,因为它的大小 (21MB) 比包罗万象的 allcountries.zip (1.4GB) 小得多。
李>根据下载页面上的readme.txt创建以下架构和表,其中字段在“主'geoname'表具有以下字段”文本下方指定。
CREATE SCHEMA geonames DEFAULT CHARSET utf8 COLLATE utf8_general_ci;
CREATE TABLE geonames.cities1000 (
id INT,
name VARCHAR(200),
ascii_name VARCHAR(200),
alternate_names VARCHAR(10000) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci,
latitude DECIMAL(10, 7),
longitude DECIMAL(10, 7),
feature_class CHAR(1),
feature_code VARCHAR(10),
country_code CHAR(2),
cc2 CHAR(60),
admin1_code VARCHAR(20),
admin2_code VARCHAR(80),
admin3_code VARCHAR(20),
admin4_code VARCHAR(20),
population BIGINT,
elevation INT,
dem INT,
timezone VARCHAR(100),
modification_date DATE
)
CHARACTER SET utf8;
只要列大小和字段类型与指定的相同,字段名称是任意的。 alternate_names
是专门用字符集 utf8mb4
定义的,因为文件中该列的值包含 MySQL 的字符集 utf8
不支持的 4 字节 unicode 字符。
检查这些参数的值:character_set_client、character_set_results、character_set_connection。 7
SHOW VARIABLES LIKE '%char%';
如果它们不是 utf8mb4,则更改它们:
SET character_set_client = utf8mb4;
SET character_set_results = utf8mb4;
SET character_set_connection = utf8mb4;
使用LOAD DATA INFILE ...
从文件导入数据
USE geonames;
LOAD DATA INFILE 'C:\\ProgramData\\MySQL\\MySQL Server 5.7\\Uploads\\cities1000.txt' INTO TABLE cities1000
CHARACTER SET utf8mb4 (id, name, ascii_name, alternate_names, latitude, longitude, feature_class, feature_code,
country_code, cc2, admin1_code, admin2_code, admin3_code, admin4_code, population, @val1,
@val2, timezone, modification_date)
SET elevation = if(@val1 = '', NULL, @val1), dem = if(@val2 = '', NULL, @val2);
语句解释:
该文件应放置在 MySQL 指定的位置,以便从文件中导入数据。您可以使用SHOW VARIABLES LIKE 'secure_file_priv';
查看位置。就我而言,它是C:\ProgramData\MySQL\MySQL Server 5.7\Uploads
。在 Windows 中,您需要使用双斜杠来表示路径中的一个斜杠。当路径未正确给出时会显示此错误:[HY000][1290] The MySQL server is running with the --secure-file-priv option so it cannot execute this statement
。
使用CHARACTER SET utf8mb4
,您可以告诉 MySQL 期望从文件中获得什么编码。如果没有明确给出,或者列编码不是 utf8mb4,就会看到类似这样的错误提示:[HY000][1300] Invalid utf8 character string: 'Gorad Safija,SOF,Serdica,Sofi,Sofia,Sofiae,Sofie,Sofii,Sofij,Sof'
。 5 sup>在我的情况下我发现它是由于替代名称中的哥特字母存在,例如?????(ID 727011),????????(ID 3464975)和??????????(ID 3893894)。这些字母需要存储为 4 字节字符 (utf8mb4),而我当时的编码是 utf8,它最多只支持 3 字节字符。 6 可以在建表后更改列编码:
ALTER TABLE cities1000 MODIFY alternate_names VARCHAR(10000) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
检查列的编码:
SELECT character_set_name, COLLATION_NAME FROM information_schema.COLUMNS WHERE table_schema = 'geonames' AND table_name = 'cities1000' AND column_name = 'alternate_names';
测试是否可以存储字符:
UPDATE cities1000 SET alternate_names = '?????' WHERE id = 1;
某些列的值在插入之前需要“改进”,例如elevation
和dem
。它们是 INT 类型,文件中它们的值可以是空字符串,不能由 INT 类型列存储。因此,您需要将这些列的空字符串转换为 null。声明的后半部分就是为了这个目的。当值没有首先转换属性时会显示此错误:[HY000][1366] Incorrect integer value: '' for column 'elevation' at row 1
。 3, 4
参考文献
-
http://www.geonames.org/
http://download.geonames.org/export/dump/
https://dev.mysql.com/doc/refman/8.0/en/load-data.html
https://dba.stackexchange.com/a/111044/94778
https://dev.mysql.com/doc/refman/5.5/en/charset-unicode-conversion.html
https://dev.mysql.com/doc/refman/5.5/en/charset-unicode-utf8mb4.html
https://***.com/a/35156926/4357087
https://dev.mysql.com/doc/refman/5.7/en/charset-connection.html
【讨论】:
谢谢,utf8mb4 解决了我遇到的一些问题。我的项目需要来自全世界的地方。所以我将 id 设为主键,并将 name 和 ascii-name 设为索引。这大大提高了性能。 太棒了。如果出现“参数未定义”错误,似乎使用 val1 和 val2 等用户值需要在连接字符串中声明“允许用户变量 = True”:***.com/a/22604492/6079533 cc2 必须至少为 100 个字符【参考方案2】:对于未来的每一个人: 在 2008 年的 geonames.org 论坛上,这是“将所有地名转储导入 MySQL” http://forum.geonames.org/gforum/posts/list/732.page
另外谷歌这个:将转储导入 [postgresql OR SQL server OR MySQL] 站点:forum.geonames.org
从 2006 年开始寻找更多答案
已编辑以提供概要:
在 geoname 官方中读到我:http://download.geonames.org/export/dump/。我们将找到关于转储文件及其内容的良好描述。
转储文件将直接导入 MySQL 数据表。例如:
SET character_set_database=utf8;
LOAD DATA INFILE '/home/data/countryInfo.txt' INTO TABLE _geo_countries IGNORE 51 LINES(ISO2,ISO3,ISO_Numeric,FIPSCode,AsciiName,Capital,Area_SqKm,Population,ContinentCode,TLD,CurrencyCode,CurrencyName,PhoneCodes,PostalCodeFormats,PostalCodeRegex,Languages,GeonameID,Neighbours,EquivalentFIPSCodes);
SET character_set_database=default;
注意字符集,因为如果我们使用 2012 年旧 phpmyadmin 的 CSV LOAD DATA 就绪导入器,即使列的排序规则设置为 utf8_general_ci,我们也可能会丢失 utf 字符
目前有 4 个基本数据表:大洲、国家(countryInfo.txt)、部门(admin1)、城市或位置(地名)
admin1, 2, 3, 4 转储文件是国家内部部门的不同级别,例如admin 1是美国的州或其他国家的省。 admin 2 比较详细,是州或省的内部部门。以此类推 3 和 4
那里列出的国家转储文件不仅包含城市,还包含该国家/地区的所有位置,甚至包括商店中心。还有一个巨大的文件,因为“allCountries.txt”从 zip 文件中提取后将超过 1GB。如果我们只想要城市,我们应该选择其中一个转储文件:cities1000.txt、cities5000.txt、cities15000.txt,其中的数字代表所列城市的最小人口。我们将城市存储在 geonames 数据表中(您可以将其称为地理位置或地理城市)。
在导入 *.txt 转储文件之前,请先研究一下 MySQL 文档中的 LOAD DATA 语法。
自述文本文件(也在转储页面的页脚中)提供了足够的描述,例如:
The main 'geoname' table has the following fields :
---------------------------------------------------
geonameid : integer id of record in geonames database
name : name of geographical point (utf8) varchar(200)
asciiname : name of geographical point in plain ascii characters, varchar(200)
alternatenames : alternatenames, comma separated varchar(5000)
latitude : latitude in decimal degrees (wgs84)
longitude : longitude in decimal degrees (wgs84)
feature class : see http://www.geonames.org/export/codes.html, char(1)
feature code : see http://www.geonames.org/export/codes.html, varchar(10)
country code : ISO-3166 2-letter country code, 2 characters
cc2 : alternate country codes, comma separated, ISO-3166 2-letter country code, 60 characters
admin1 code : fipscode (subject to change to iso code), see exceptions below, see file admin1Codes.txt for display names of this code; varchar(20)
admin2 code : code for the second administrative division, a county in the US, see file admin2Codes.txt; varchar(80)
admin3 code : code for third level administrative division, varchar(20)
admin4 code : code for fourth level administrative division, varchar(20)
population : bigint (8 byte int)
elevation : in meters, integer
dem : digital elevation model, srtm3 or gtopo30, average elevation of 3''x3'' (ca 90mx90m) or 30''x30'' (ca 900mx900m) area in meters, integer. srtm processed by cgiar/ciat.
timezone : the timezone id (see file timeZone.txt) varchar(40)
modification date : date of last modification in yyyy-MM-dd format
还有关于 varchar(5000) 我们应该知道 MySQL 5.0 或更高版本中每行的 64kb 大小: Is a VARCHAR(20000) valid in MySQL?
【讨论】:
【参考方案3】:我通过查看包含在您链接到的名为“主 'GeoName' 表具有以下字段的部分中的 zip 文件中的自述文件”找到以下内容:
首先在您的 MySQL 实例上创建数据库和表。字段的类型在我刚刚引用上面标题的部分的每一行中给出。
CREATE DATABASE DO_test;
CREATE TABLE `DO_test`.`DO_table` (
`geonameid` INT,
`name` varchar(200),
`asciiname` varchar(200),
`alternatenames` varchar(5000),
`latitude` DECIMAL(10,7),
`longitude` DECIMAL(10,7),
`feature class` char(1),
`feature code` varchar(10),
`country code` char(2),
`cc2` char(60),
`admin1 code` varchar(20),
`admin2 code` varchar(80),
`admin3 code` varchar(20),
`admin4 code` varchar(20),
`population` bigint,
`elevation` INT,
`gtopo30` INT,
`timezone` varchar(100),
`modification date` date
)
CHARACTER SET utf8;
创建表后,您可以从文件中导入数据。字段由制表符分隔,行作为换行符:
LOAD DATA INFILE '/path/to/your/file/DO.txt' INTO TABLE `DO_test`.`DO_table`;
【讨论】:
糟糕,您需要对纬度和经度做一些不同的事情。我正在努力解决这个问题。我认为它们应该是“POINT”而不是 DECIMAL。 由于某种原因,我得到:错误代码:29 找不到文件“/home/blueprint/DO.txt”(错误代码:13)我很确定该文件在那里。跨度> @LuisDUrraca:你是在 Mac 上吗?错误代码 13 表示 MySQL 无法看到该文件。我有一台 Mac,我将 DO.txt 文件放在 Mac 的 mysql 目录中。比弄清楚为什么 MySQL 看不到每个人都已完全读取的文件更容易。在我的机器上,它位于 /usr/local/mysql 中。 我在 Linux Ubuntu 10.10 上。我的 MySQL 目录是 var/lib/mysql 但也无法访问它。让我继续努力。 @LuisDUrraca:您是否尝试将其放入 /tmp 并从那里加载?【参考方案4】:我最近制作了一个 shell 脚本,可以从 geonames 站点下载最新数据并将它们导入 MySQL 数据库。它基于 GeoNames 论坛上的知识,为我节省了很多时间。
它是第一个版本,但功能齐全。也许它可以提供帮助。
您可以通过http://codigofuerte.github.com/GeoNames-MySQL-DataImport/ 访问它
【讨论】:
谢谢。这为我们省去了一些麻烦。似乎甚至可以与 Cygwin 一起使用(在我同事的计算机上看到它)。现在让它在我的 linux 机器上运行。似乎有效,但需要很长时间! :) 谢谢,这非常有用以上是关于将 geonames.org 数据库中的数据导入 MySQL DB的主要内容,如果未能解决你的问题,请参考以下文章