• 设为首页
  • 点击收藏
  • 手机APP
    手机扫一扫下载
    华域联盟APP
  • 关注官方公众号
    微信扫一扫关注
    华域联盟公众号
hotWEB访问日志自动化剖析浅谈

1.概略最近经常需求剖析WEB访问日志,从中发现非法央求,然后做相应安全检查,为了便当,所以写了一个日志 详情

如何将 JSON, Text, XML, CSV 数据文件导入 MySQL ...

0
回复
113
查看
[复制链接]
发表于 2018-1-20 17:06:14 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有帐号?立即注册 新浪微博登陆

x
  将外部数据导入(import)数据库是在数据库应用中一个很常见的需求。其实这就是在数据的管理和操作中的ETL (Extract, transform, load)的L (Load)部分,也就是说,将特定结构(structure)或者格式(format)的数据导入某个目的地(比如数据库,这里我们讨论MySQL)。
$ x) C2 V' J5 f* ?: @4 x/ A/ ]        20160411175312550715.PNG
. K; y' \# T& `  o/ `. r, D* e, `- S          本文要讨论的内容,是如何方便地将多种格式(JSON, Text, XML, CSV)的数据导入MySQL之中。5 K: Z& e9 n3 U6 G
          本文大纲:
, r, u0 S, s- ^$ t* ?- X) Z
           
      m3 B* m& B5 t5 R3 S
  •                 将Text文件(包括CSV文件)导入MySQL
    ! j7 l* v( H4 |) i+ X& J        : K2 `9 c; B. g, i' E' T5 A0 Q& b3 N: F
  •                 将XML文件导入MySQL: h4 G4 t! p# m5 ~* x6 c
           
    9 V7 I& {* A4 _4 V
  •                 将JSON文件导入MySQL6 x' L4 [! o( m1 o) w
            ) g& g% }7 v6 U8 Q/ ~
  •                 使用MySQL workbench的Table Data Export and Import Wizard进行JSON或CSV文件的导入导出
    9 Z5 B1 @4 ^; m
         1. 将Text文件(包括CSV文件)导入MySQL
( C% I9 m: p9 Z$ u( M% Q+ O7 I4 ~, m0 f4 H; u5 d+ D
          这里我们的讨论是基于一个假定,Text file和CSV file是有着比较规范的格式的(properly formatted),比如说每行的每个数据域(field)之间是由一个共同的分隔符(比如tab: t)分隔的。) S0 O+ {; g* u  i
          那么首先,你需要根据你的数据的格式(有哪些域),来设计好数据库的对应的表 (的Schema)。
5 i0 Y+ y, i4 p          举个例子,要处理的Text文件或者CSV文件是以t作为分隔符的,每行有id, name, balance这么三个数据域,那么首先我们需要在数据库中创建这个表:
  1. CREATE TABLE sometable(id INT, name VARCHAR(255), balance DECIMAL(8,4));
复制代码
  创建成功以后就可以导入了。操作方式很简单:
  1. LOAD DATA LOCAL INFILE '你的文件路径(如~/file.csv)' INTO TABLE sometable FIELDS TERMINATED BY 't' [ENCLOSED BY '"'(可选)] LINES TERMINATED BY 'n' (id, name, balance)
复制代码
  这里要注意的是,我们需要开启local-infile这个MySQL的配置参数,才能够成功导入。究其原因,从MySQL的Manual中可以看到这么一段话:
                LOCAL works only if your server and your client both have been configured to permit it. For example, if mysqld was started with --local-infile=0, LOCAL does not work. See Section 6.1.6, “Security Issues with LOAD DATA LOCAL”.
  这是MySQL出于安全考虑的默认配置。因此,我们需要在配置文件my.cnf中(以Debian发行版的Linux, 如Ubuntu为例, 即是在/etc/my.cnf中),确保:
  1. local-infile=1
复制代码
  抑或是在命令行启动MySQL时加上--local-infile这一项:
  1. mysql --local-infile -uroot -pyourpwd yourdbname
复制代码
  此外,我们也可以使用MySQL的一个官方导入程序 mysqlimport,这个程序本质上就是为LOAD DATA FILE提供了一个命令行的interface,很容易理解,我们这里就不再详述。
- v8 T: S5 n+ F         2. 将XML文件导入MySQL
& D7 E5 q- S3 ^+ e; k! W$ k2 S) W9 T0 D# n# y* U; N: R
          这件事的完成方式,与我们的XML的形式有着很大的关系。
) x1 P8 U0 d5 k7 e8 m( k          举个例子说,当你的XML数据文件有着很非常规范的格式,比如:
  1. <?xml version="1.0"?> <row> <field name="id">1</field> <field name="name">Free</field> <field name="balance">2333.3333</field> </row> <row> <field name="id">2</field> <field name="name">Niki</field> <field name="balance">1289.2333</field> </row>
复制代码
  或者
  1. <row column1="value1" column2="value2" .../>
复制代码
  我们就可以很方便使用LOAD XML来导入,这里可以参见MySQL的官方手册--LOAD XML Syntax。% O5 c! F! d" ?9 v) Z/ Z& Z& _
          然而我们可能有另外一些需求,比如说,我们可能会想要将XML文件的域映射到不同名字的列(TABLE COLUMN)之中。这里要注意,MySQL v5.0.7以后,MySQL的Stored Procedure中不能再运行LOAD XML INFILE 或者LOAD DATA INFILE。所以转换的程序(procedure)的编写方式与在此之前有所不同。这里,我们需要使用 Load_File()和ExtractValue()这两个函数。* _  N  u8 g1 g  G7 w
          以下是一个示例XML文件和程序:文件:
  1. <?xml version="1.0"?>
  2. <some_list> <someone id="1" fname="Rob" lname="Gravelle"/> <someone id="2" fname="Al" lname="Bundy"/> <someone id="3" fname="Little" lname="Richard"/>
  3. </some_list>
复制代码
  程序:
  1. DELIMITER $$
  2. CREATE DEFINER=`root`@`localhost` PROCEDURE `import_some_xml`(path varchar(255), node varchar(255))
  3. BEGIN declare xml_content text; declare v_row_index int unsigned default 0; declare v_row_count int unsigned; declare v_xpath_row varchar(255); set xml_content = load_file(path); -- calculate the number of row elements. set v_row_count = extractValue(xml_content, concat(&#39;count(&#39;, node, &#39;)&#39;)); -- loop through all the row elements while v_row_index < v_row_count do set v_row_index = v_row_index + 1; set v_xpath_row = concat(node, &#39;[&#39;, v_row_index, &#39;]/@*&#39;); insert into applicants values ( extractValue(xml_content, concat(v_xpath_row, &#39;[1]&#39;)), extractValue(xml_content, concat(v_xpath_row, &#39;[2]&#39;)), extractValue(xml_content, concat(v_xpath_row, &#39;[3]&#39;)) ); end while;
  4. END
复制代码
  在MySQL中,使用它进行导入:
  1. call import_some_xml(&#39;你的XML文件路径&#39;, &#39;/some_list/someone&#39;);
复制代码
  程序相当的直白,只要了解一下MySQL脚本编写即可。
, `% s9 O, _: d+ G- V! i6 e' n          这里提一下DELIMITER $$。我们知道MySQL的命令分隔符默认为分号,然而脚本中很显然是有分号的,但是我们并不希望立即执行,所以我们需要临时更改分隔符。+ ]  c* d8 y9 x7 q" |2 I/ F
         3. 将JSON文件导入MySQL
1 J# `; Q# k  r8 o; f0 }
9 g  v/ R( u' B0 t! A          如何将JSON文件导入MySQL中,是一个很有趣的话题。JSON是一种现在相当常用的文件结构,所以掌握它的导入具有比较广泛的意义。
7 G9 m4 D5 u( \! I- T% ^          很多时候,我们处理的JSON数据是以如下形式出现的:
  1. {"name":"Julia","gender":"female"}
  2. {"name":"Alice","gender":"female"}
  3. {"name":"Bob","gender":"male"}
  4. {"name":"Julian","gender":"male"}
复制代码
  而并不是规整的[{},{},{},{}](一些NoSQL数据库的Export)。
4 m& {: F6 _, z) e9 ], F          这样的形势对于载入有一个好处:因为每一行是一个JSON Object,所以我们便可以按行处理此文件,而不需要因为JSON的严格结构将整个文件(比如一个许多G的.json文件)全部载入。) h; F" T4 X! e  }) q" M2 U
          方式一 使用common-schema3 X  r& B5 B. D# O% K8 A, K6 d
6 z" C; R. u- m. l1 X
          common-schema是一个应用很广泛的MySQL的框架,它有着很丰富的功能和详细的文档。我们可以使用它的JSON解析的功能。(它还具有JSON转换成XML等等方便的功能)- v2 L2 B. z* }" @
          具体说来,将common-schema导入之后,使用它的extract_json_value函数即可。源码中:
  1. LOAD DATA LOCAL INFILE &#39;你的文件路径(如~/file.csv)&#39; INTO TABLE sometable FIELDS TERMINATED BY &#39;t&#39; [ENCLOSED BY &#39;"&#39;(可选)] LINES TERMINATED BY &#39;n&#39; (id, name, balance)0
复制代码
  该函数接受两个参数,一个是json_text,表示json文件的内容,另一个是xpath,表示数据的结构(这里可以类比XML文件的处理)。很多读者应该知道,XPath是用来对XML中的元素进行定位的,这里也可以作一样的理解。
6 n0 Q, w) c0 x& @1 N: S$ ~          以本段开始的几行JSON为例,这里common-schema的使用如下例:
  1. LOAD DATA LOCAL INFILE &#39;你的文件路径(如~/file.csv)&#39; INTO TABLE sometable FIELDS TERMINATED BY &#39;t&#39; [ENCLOSED BY &#39;"&#39;(可选)] LINES TERMINATED BY &#39;n&#39; (id, name, balance)1
复制代码
  关于event_data,我们需要先理解LOAD DATA INFILE是一个event,不同的event type对应不同的event data。这部分知识可以参看Event Data for Specific Event Types
3 Z: t5 ]5 |+ k  t0 a# f          如果感兴趣,可以参看其源码。参看一个受到广泛使用的项目的源码,对于自身成长是很有益的。
7 U7 I; z% p1 {( `' C' l! d2 X4 d          当然了,我们也可以像之前处理XML文件导入一样,自己编写程序。这里便不再给出实例程序,有兴趣的读者可以自行编写或者跟笔者交流。
8 ?( v# O) y  W" x) U          方式二 使用mysqljsonimport3 R9 Z* A9 |* a7 W! r

( z; i1 o! ?/ s4 i- o1 U% R/ j          这是Anders Karlsson的一个完成度很高的作品。这一份程序由C写成。它依赖于一个JSON Parser,Jansson。他们都有着比较好的维护和文档,所以使用上体验很好。- t5 w5 z$ {; t) P1 ~4 O$ C
          mysqljsonimport的下载在SourceForge上。具体使用参照其文档即可。
* I  L8 M2 N2 ~- {          为了方便不熟悉源码安装的朋友,笔者在这里提一下安装流程和注意事项。安装命令顺序如下:
  1. LOAD DATA LOCAL INFILE &#39;你的文件路径(如~/file.csv)&#39; INTO TABLE sometable FIELDS TERMINATED BY &#39;t&#39; [ENCLOSED BY &#39;"&#39;(可选)] LINES TERMINATED BY &#39;n&#39; (id, name, balance)2
复制代码
  --with-mysql这一步不是必要的,只要你安装的mysql的路径是系统的默认路径。很关键的,而且很容易被不熟悉的朋友忽略的是,这一个C程序要成功编译和运行,是需要MySQL的C API的,所以需要安装的依赖,除了jansson,还有libmysqlclient-dev。  ]: _0 Y3 D& g9 u( ^
          jansson的安装就是简单的源码安装,libmysqlclient-dev则可以使用包管理工具(比如ubuntu中使用apt-get即可;编译和安装前,建议先sudo apt-get update以避免不必要的麻烦)。* ?. H3 I9 f# x8 F9 b" ^/ `
          导入命令:
  1. LOAD DATA LOCAL INFILE &#39;你的文件路径(如~/file.csv)&#39; INTO TABLE sometable FIELDS TERMINATED BY &#39;t&#39; [ENCLOSED BY &#39;"&#39;(可选)] LINES TERMINATED BY &#39;n&#39; (id, name, balance)3
复制代码
  还有一个parser,作者是Kazuho,感兴趣的读者可以参看一下,他的相关博文是mysql_json - a MySQL UDF for parsing JSON ,github项目是mysql_json。, M8 y! ^& U7 Y% Z
         4. 使用MySQL workbench
, V) i. a6 y. W2 s! p, U0 ]) X* r9 r5 d8 [+ g8 ^, g7 a/ |8 a
          Workbench这个工具对于许多不熟悉SQL语言或者命令行的朋友还是很方便和友好的。利用它,可以方便地导入和导出CSV和JSON文件。% @0 U+ g+ V! \& {
          具体操作图例参见MySQL官方手册即可:Table Data Export and Import Wizard,这里不再赘述。; k; ?9 @7 C$ M, D) x1 U2 W
        20160411175312550715.PNG
4 F' s2 F/ G' z2 v& P         总结* v8 x$ E* N) B, w
6 I5 E3 w" i0 v& [* o
          本文介绍了将不同格式(JSON, Text, XML, CSV)的文件导入MySQL数据库的一些详细手段,并进行了一些分析,目的在于帮助读者扫除一些导入的障碍,理清一些概念。之所以没有讨论导出,是因为导出是一个MySQL到外的操作,是以MySQL本身为转移的,只要参考MySQL本身的机理即可。' m# z) R$ e& A+ C, P
          真正对于大量数据的导入导出,需要思考的问题会很多(比如说在导入时,如何考虑Sharding),这需要另开一篇讨论了。( b8 h/ G4 }. Q$ t; x/ a  W. F' F
          谢谢阅读,欢迎指正。



上一篇:请关掉你的数据库连接!并且请使用数据库连接池
下一篇:Couchbase 介绍 - 更好的 Cache 系统

扫描微信二维码

关注华域联盟公众号

随时了解更新最新资讯

在线客服(服务时间 9:00~18:00)

在线QQ客服

电邮:admin@cnhackhy.com

Powered by 华域联盟! © 2015-2019

备案号:蒙ICP备17000689号-2蒙公网安备 15062202000105号中国互联网举报中心 Free counters!