重庆分公司,新征程启航
为企业提供网站建设、域名注册、服务器等服务
mysql插入json自动转义方法,通过json_encode后的数据写入Mysql数据库时,mysql对会json_encode值里面有中文的unicode反斜杠进行转义,这是在数据库层的转义。
站在用户的角度思考问题,与客户深入沟通,找到周宁网站设计与周宁网站推广的解决方案,凭借多年的经验,让设计与互联网技术结合,创造个性化、用户体验好的作品,建站类型包括:网站设计制作、网站设计、企业官网、英文网站、手机端网站、网站推广、主机域名、网站空间、企业邮箱。业务覆盖周宁地区。
将外部数据导入(import)数据库是在数据库应用中一个很常见的需求。其实这就是在数据的管理和操作中的ETL (Extract, transform, load)的L (Load)部分,也就是说,将特定结构(structure)或者格式(format)的数据导入某个目的地(比如数据库,这里我们讨论MySQL)。
ETL Process
本文要讨论的内容,是如何方便地将多种格式(JSON, Text, XML, CSV)的数据导入MySQL之中。
本文大纲:
将Text文件(包括CSV文件)导入MySQL
将XML文件导入MySQL
将JSON文件导入MySQL
使用MySQL workbench的Table Data Export and Import Wizard进行JSON或CSV文件的导入导出
1. 将Text文件(包括CSV文件)导入MySQL
这里我们的讨论是基于一个假定,Text file和CSV file是有着比较规范的格式的(properly formatted),比如说每行的每个数据域(field)之间是由一个共同的分隔符(比如tab: \t)分隔的。
那么首先,你需要根据你的数据的格式(有哪些域),来设计好数据库的对应的表 (的Schema)。
举个例子,要处理的Text文件或者CSV文件是以\t作为分隔符的,每行有id, name, balance这么三个数据域,那么首先我们需要在数据库中创建这个表:
CREATE TABLE sometable(id INT, name VARCHAR(255), balance DECIMAL(8,4));
创建成功以后就可以导入了。操作方式很简单:
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中),确保:
local-infile=1
抑或是在命令行启动MySQL时加上--local-infile这一项:
mysql --local-infile -uroot -pyourpwd yourdbname
此外,我们也可以使用MySQL的一个官方导入程序mysqlimport ,这个程序本质上就是为LOAD DATA FILE提供了一个命令行的interface,很容易理解,我们这里就不再详述。
2. 将XML文件导入MySQL
这件事的完成方式,与我们的XML的形式有着很大的关系。
举个例子说,当你的XML数据文件有着很非常规范的格式,比如:
?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
或者
row column1="value1" column2="value2" .../
我们就可以很方便使用LOAD XML来导入,这里可以参见MySQL的官方手册--LOAD XML Syntax。
然而我们可能有另外一些需求,比如说,我们可能会想要将XML文件的域映射到不同名字的列(TABLE COLUMN)之中。这里要注意,MySQL v5.0.7以后,MySQL的Stored Procedure中不能再运行LOAD XML INFILE 或者LOAD DATA INFILE。所以转换的程序(procedure)的编写方式与在此之前有所不同。这里,我们需要使用Load_File()和ExtractValue()这两个函数。
以下是一个示例XML文件和程序:
文件:
?xml version="1.0"?
some_list
someone id="1" fname="Rob" lname="Gravelle"/
someone id="2" fname="Al" lname="Bundy"/
someone id="3" fname="Little" lname="Richard"/
/some_list
程序:
DELIMITER $$
CREATE DEFINER=`root`@`localhost` PROCEDURE `import_some_xml`(path varchar(255), node varchar(255))
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('count(', node, ')'));
-- 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, '[', v_row_index, ']/@*');
insert into applicants values (
extractValue(xml_content, concat(v_xpath_row, '[1]')),
extractValue(xml_content, concat(v_xpath_row, '[2]')),
extractValue(xml_content, concat(v_xpath_row, '[3]'))
);
end while;
END
在MySQL中,使用它进行导入:
call import_some_xml('你的XML文件路径', '/some_list/someone');
程序相当的直白,只要了解一下MySQL的脚本编写即可。
这里提一下DELIMITER $$。我们知道MySQL的命令分隔符默认为分号,然而脚本中很显然是有分号的,但是我们并不希望立即执行,所以我们需要临时更改分隔符。
3. 将JSON文件导入MySQL
如何将JSON文件导入MySQL中,是一个很有趣的话题。JSON是一种现在相当常用的文件结构,所以掌握它的导入具有比较广泛的意义。
很多时候,我们处理的JSON数据是以如下形式出现的:
{"name":"Julia","gender":"female"}
{"name":"Alice","gender":"female"}
{"name":"Bob","gender":"male"}
{"name":"Julian","gender":"male"}
而并不是规整的[{},{},{},{}](一些NoSQL数据库的Export)。
这样的形势对于载入有一个好处:因为每一行是一个JSON Object,所以我们便可以按行处理此文件,而不需要因为JSON的严格结构将整个文件(比如一个许多G的.json文件)全部载入。
方式一 使用common-schema
common-schema是一个应用很广泛的MySQL的框架,它有着很丰富的功能和详细的文档。我们可以使用它的JSON解析的功能。(它还具有JSON转换成XML等等方便的功能)
具体说来,将common-schema导入之后,使用它的extract_json_value函数即可。源码中:
create function extract_json_value(
json_text text charset utf8,
xpath text charset utf8
) returns text charset utf8
该函数接受两个参数,一个是json_text,表示json文件的内容,另一个是xpath,表示数据的结构(这里可以类比XML文件的处理)。很多读者应该知道,XPath是用来对XML中的元素进行定位的,这里也可以作一样的理解。
以本段开始的几行JSON为例,这里common-schema的使用如下例:
select common_schema.extract_json_value(f.event_data,'/name') as name, common_schema.extract_json_value(f.event_data,'/gender') as gender, sum(f.event_count) as event_count from json_event_fact f group by name, gender;
关于event_data,我们需要先理解LOAD DATA INFILE是一个event,不同的event type对应不同的event data。这部分知识可以参看Event Data for Specific Event Types
如果感兴趣,可以参看其源码。参看一个受到广泛使用的项目的源码,对于自身成长是很有益的。
当然了,我们也可以像之前处理XML文件导入一样,自己编写程序。这里便不再给出实例程序,有兴趣的读者可以自行编写或者跟笔者交流。
方式二 使用mysqljsonimport
这是Anders Karlsson的一个完成度很高的作品。这一份程序由C写成。它依赖于一个JSON Parser,Jansson。他们都有着比较好的维护和文档,所以使用上体验很好。
mysqljsonimport的下载在SourceForge上。具体使用参照其文档即可。
为了方便不熟悉源码安装的朋友,笔者在这里提一下安装流程和注意事项。
安装命令顺序如下:
$ wget
$ tar xvfz mysqljsonimport-1.6.tar.gz
$ cd mysqljsonimport-1.6
$ ./configure –-with-mysql=/xxx/mysql
$ make
$ make check
$ sudo make install
--with-mysql这一步不是必要的,只要你安装的mysql的路径是系统的默认路径。很关键的,而且很容易被不熟悉的朋友忽略的是,这一个C程序要成功编译和运行,是需要MySQL的C API的,所以需要安装的依赖,除了jansson,还有libmysqlclient-dev。
jansson的安装就是简单的源码安装,libmysqlclient-dev则可以使用包管理工具(比如ubuntu中使用apt-get即可;编译和安装前,建议先sudo apt-get update以避免不必要的麻烦)。
导入命令:
$ ./mysqljsonimport –-database test –-table tablename jsonfilename
还有一个parser,作者是Kazuho,感兴趣的读者可以参看一下,他的相关博文是mysql_json - a MySQL UDF for parsing JSON ,github项目是mysql_json。
4. 使用MySQL workbench
Workbench这个工具对于许多不熟悉SQL语言或者命令行的朋友还是很方便和友好的。利用它,可以方便地导入和导出CSV和JSON文件。
具体操作图例参见MySQL官方手册即可:Table Data Export and Import Wizard,这里不再赘述。
文/freenik(简书作者)
原文链接:
解析json字符串,定义一个dto对象,字段名和类型和json里面一致,然后用jdbc连接数据库,insert into插入表中,代码自己写吧,没时间帮你写
我们知道,JSON是一种轻量级的数据交互的格式,大部分NO SQL数据库的存储都用JSON。MySQL从5.7开始支持JSON格式的数据存储,并且新增了很多JSON相关函数。MySQL 8.0 又带来了一个新的把JSON转换为TABLE的函数JSON_TABLE,实现了JSON到表的转换。
举例一
我们看下简单的例子:
简单定义一个两级JSON 对象
mysql set @ytt='{"name":[{"a":"ytt","b":"action"}, {"a":"dble","b":"shard"},{"a":"mysql","b":"oracle"}]}';Query OK, 0 rows affected (0.00 sec)
第一级:
mysql select json_keys(@ytt);+-----------------+| json_keys(@ytt) |+-----------------+| ["name"] |+-----------------+1 row in set (0.00 sec)
第二级:
mysql select json_keys(@ytt,'$.name[0]');+-----------------------------+| json_keys(@ytt,'$.name[0]') |+-----------------------------+| ["a", "b"] |+-----------------------------+1 row in set (0.00 sec)
我们使用MySQL 8.0 的JSON_TABLE 来转换 @ytt。
mysql select * from json_table(@ytt,'$.name[*]' columns (f1 varchar(10) path '$.a', f2 varchar(10) path '$.b')) as tt;
+-------+--------+
| f1 | f2 |
+-------+--------+
| ytt | action |
| dble | shard |
| mysql | oracle |
+-------+--------+
3 rows in set (0.00 sec)
举例二
再来一个复杂点的例子,用的是EXPLAIN 的JSON结果集。
JSON 串 @json_str1。
set @json_str1 = ' { "query_block": { "select_id": 1, "cost_info": { "query_cost": "1.00" }, "table": { "table_name": "bigtable", "access_type": "const", "possible_keys": [ "id" ], "key": "id", "used_key_parts": [ "id" ], "key_length": "8", "ref": [ "const" ], "rows_examined_per_scan": 1, "rows_produced_per_join": 1, "filtered": "100.00", "cost_info": { "read_cost": "0.00", "eval_cost": "0.20", "prefix_cost": "0.00", "data_read_per_join": "176" }, "used_columns": [ "id", "log_time", "str1", "str2" ] } }}';
第一级:
mysql select json_keys(@json_str1) as 'first_object';+-----------------+| first_object |+-----------------+| ["query_block"] |+-----------------+1 row in set (0.00 sec)
第二级:
mysql select json_keys(@json_str1,'$.query_block') as 'second_object';+-------------------------------------+| second_object |+-------------------------------------+| ["table", "cost_info", "select_id"] |+-------------------------------------+1 row in set (0.00 sec)
第三级:
mysql select json_keys(@json_str1,'$.query_block.table') as 'third_object'\G*************************** 1. row ***************************third_object: ["key","ref","filtered","cost_info","key_length","table_name","access_type","used_columns","possible_keys","used_key_parts","rows_examined_per_scan","rows_produced_per_join"]1 row in set (0.01 sec)
第四级:
mysql select json_extract(@json_str1,'$.query_block.table.cost_info') as 'forth_object'\G*************************** 1. row ***************************forth_object: {"eval_cost":"0.20","read_cost":"0.00","prefix_cost":"0.00","data_read_per_join":"176"}1 row in set (0.00 sec)
那我们把这个JSON 串转换为表。
SELECT * FROM JSON_TABLE(@json_str1,
"$.query_block"
COLUMNS(
rowid FOR ORDINALITY,
NESTED PATH '$.table'
COLUMNS (
a1_1 varchar(100) PATH '$.key',
a1_2 varchar(100) PATH '$.ref[0]',
a1_3 varchar(100) PATH '$.filtered',
nested path '$.cost_info'
columns (
a2_1 varchar(100) PATH '$.eval_cost' ,
a2_2 varchar(100) PATH '$.read_cost',
a2_3 varchar(100) PATH '$.prefix_cost',
a2_4 varchar(100) PATH '$.data_read_per_join'
),
a3 varchar(100) PATH '$.key_length',
a4 varchar(100) PATH '$.table_name',
a5 varchar(100) PATH '$.access_type',
a6 varchar(100) PATH '$.used_key_parts[0]',
a7 varchar(100) PATH '$.rows_examined_per_scan',
a8 varchar(100) PATH '$.rows_produced_per_join',
a9 varchar(100) PATH '$.key'
),
NESTED PATH '$.cost_info'
columns (
b1_1 varchar(100) path '$.query_cost'
),
c INT path "$.select_id"
)
) AS tt;
+-------+------+-------+--------+------+------+------+------+------+----------+-------+------+------+------+------+------+------+
| rowid | a1_1 | a1_2 | a1_3 | a2_1 | a2_2 | a2_3 | a2_4 | a3 | a4 | a5 | a6 | a7 | a8 | a9 | b1_1 | c |
+-------+------+-------+--------+------+------+------+------+------+----------+-------+------+------+------+------+------+------+
| 1 | id | const | 100.00 | 0.20 | 0.00 | 0.00 | 176 | 8 | bigtable | const | id | 1 | 1 | id | NULL | 1 |
| 1 | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | 1.00 | 1 |
+-------+------+-------+--------+------+------+------+------+------+----------+-------+------+------+------+------+------+------+
2 rows in set (0.00 sec)
当然,JSON_table 函数还有其他的用法,我这里不一一列举了,详细的参考手册。
请点击输入图片描述
MySQL支持JSON数据类型。相比于Json格式的字符串类型,JSON数据类型的优势有:
存储在JSON列中的任何JSON文档的大小都受系统变量 max_allowed_packet 的值的限制,可以使用 JSON_STORAGE_SIZE() 函数获得存储JSON文档所需的空间。
在MySQL8.0中,优化器可以执行JSON列的局部就地更新,而不用删除旧文档再将整个新文档写入该列。局部更新的条件:
JSON数组包含在 字符 [ 和 ] 字符中,其中为一个由逗号分隔的值列表:
JSON对象包含在字符 { 和 } 字符中,其中为一组由逗号分隔的键值对,键必须是字符串:
在JSON数组和JSON对象的值中允许嵌套:
下例中向创建一个只有一个JSON列的表格 t_json ,并向其中添加JSON值:
若添加的值为非JSON格式,则报错:
查看 t_json :
如果传入的参数不能组成键值对,则报错:
因此我们也可以使用以上三种方法向表中添加JSON值,可以一定程度地避免输入格式错误:
解析字符串并发现字符串是有效的JSON文档时,它在被解析时也会被规范化。对于重复的键( key ),后面的值( value )会覆盖前面的值。如下:
这种“覆盖”在向JSON列添加值时也会发生。
在MySQL8.0.3之前的版本中,与此相反,对于被重复的键,它的第一个值会被保留,后添加的值则会被抛弃。
MySQL8.0.3及更高版本中,有两种合并函数: JSON_MERGE_PRESERVE() 和 JSON_MERGE_PATCH() 。下面具讨论它们的区别。
合并数组时, JSON_MERGE_PRESERVE 只保留最后传入的数组参数,而 JSON_MERGE_PRESERVE 则按传入顺序将数组参数连接。
合并对象时,对于重复键, JSON_MERGE_PRESERVE 只保留最后传入的键值,而 JSON_MERGE_PRESERVE 重复键的所有值保留为数组。
在了解搜索和修改JSON值之前,先来看看JSON的路径语法。
JSON_EXTRACT 提取JSON值,直接看例子:
JSON_REPLACE 与 JSON_SET 的区别:
JSON_INSERT 和 JSON_SET :
JSON_REMOVE :
可以使用 = , , = , , = , , != ,和 = 对JSON值进行比较。
JSON值的比较先比较值的类型。如果类型不同,则直接 返回类型的优先级的比较结果;如果类型相同,再进行值的内容的比较。
OPAQUE 值是不属于其他类型的值。
转换规则为: