MySQL LOAD DATA INFILE

MySQL LOAD DATA INFILE

LOAD DATA INFILE语句是MySQL中用来批量、快速导入数据的一种方式,和SELECT ... INTO OUTFILE 作用是相反的

 

一、完整语法

LOAD DATA [LOW_PRIORITY | CONCURRENT] [LOCAL] INFILE 'file_name'
    [REPLACE | IGNORE]
    INTO TABLE tbl_name
    [PARTITION (partition_name,...)]
    [CHARACTER SET charset_name]
    [{FIELDS | COLUMNS}
        [TERMINATED BY 'string']
        [[OPTIONALLY] ENCLOSED BY 'char']
        [ESCAPED BY 'char']
    ]
    [LINES
        [STARTING BY 'string']
        [TERMINATED BY 'string']
    ]
    [IGNORE number {LINES | ROWS}]
    [(col_name_or_user_var,...)]
    [SET col_name = expr,...]

 关键字解释:

LOW_PRIORITY | CONCURRENT:若指定LOW_PRIORITY,则该LOAD DATA 语句的真正执行将推迟到没有客户端在读取所设计的表时(只对只支持表锁的引擎有效);

LOCAL:若未指定该关键字,则说明文件在MySQL所在机子上,文件由MySQL服务器去读取,此时如果后面指定为文件路径为相对路径,1.如果路径以./开头,那么路径是相对于MySQL的data目录的,2.如果路径不是以./开头,那么路径是相对于默认数据库的目录的;若指定了该关键字,则说明文件在客户端机子上,文件由客户端去读取并通过网络发送给MySQL服务器

REPLACE | IGNORE :当插入的行遇到UNIQUE字段重复时,若指定为REPLACE,则用该行替换原来的行;若指定为IGNORE,则忽略改行

PARTITION (partition_name,...):将数据插入指定分区

CHARACTER SET:若不指定字符集,MySQL默认使用character_set_database变量指定的字符集去读取文件,若文件字符集不同,则应指定该关键字

FIELDS TERMINATED BY:字段值的分隔符,若不指定则默认为 '\t'

FIELDS ENCLOSED BY:字段值的包括符,若不指定则默认为 ''

FIELDS ESCAPED BY:字段值的转义字符,若不指定则默认为'\\'

LINES TERMINATED BY:指定行分隔符,若不指定则默认为为系统的默认行分隔符(‘\r\n‘ on windows,'\n' on linux)

LINES STARTING BY:若指定该值为xxx,则MySQL会自动去掉xxx及其前面的字符,若某行不包含xxx,则改行将被忽略,若不指定默认为'',比如执行以下语句:

 

LOAD DATA INFILE '/tmp/test.txt' INTO TABLE test
  FIELDS TERMINATED BY ','  LINES STARTING BY 'xxx';

 对应的文件内容为:

 

 

xxx"abc",1
something xxx"def",2
"ghi",3

 则实际插入的行为("abc", 1), ("def", 2)

 

IGNORE LINES | ROWS:忽略文件开头的指定行,比如指定为2,那么MySQL只会解析并插入第三行及后面的数据

 

 二、协议交换细节

1.用户发起LOAD DATA AINFILE语句,客户端工具向MySQL服务器发送一个Query Packet(command type = 0x03),内含LOAD DATA INFILE完整SQL

2.MySQL解析该SQL,发现是LOAD DATA INFILE,此时,若MySQL发现SQL中不含LOCAL关键字,则MySQL直接根据路径去本地取文件,跳至第4步;若发现包含LOCAL关键字,则MySQL发送一个请求文件(命令标识为0xFB)的包到客户端,MySQL进入等待接受文件的状态(当前连接不可进行其他操作)

3.客户端接受到来自MySQL服务器的请求文件的命令,客户端解析出报文中的路径,并根据该路径去本地读取文件,将该文件分段发送给MySQL服务器(至于这个分段的大小是多少应该不是绝对的,调试时发现是16384字节,可能根据客户端不同而不同吧,因为理论上MySQL的报文最大长度远远不止16384,而是2^24 - 1),发送完文件内容后,最后发送一个空包(报文序列为[0, 0, 0, packetId]),以此告诉MySQL服务器文件内容已发送完毕。

4.MySQL服务器获取到完整的文件内容,开始解析并插入数据,完后回复一个OKPacket,告诉客户端affected rows,warnings条数等信息

 

以下是带有LOCAL的报文交换示意图:

MySQL LOAD DATA INFILE_第1张图片
 
 

三、示例

表:

CREATE TABLE `department` (
  `id` int(11) NOT NULL,
  `name` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE `employee` (
  `id` int(11) NOT NULL,
  `name` varchar(255) DEFAULT NULL,
  `dept_id` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `dept_id` (`dept_id`),
  CONSTRAINT `employee_ibfk_1` FOREIGN KEY (`dept_id`) REFERENCES `department` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8

 

准备插入employee的文件内容:

"0","a","0"
foo"1","a\"","0"
"2","a","0"
xxxxxxfoo"3","b","0"

 执行SQL及其结果:

mysql> load data local infile 'C:\\Users\\lixiaohui\\Desktop\\source.sql' into table employee character set utf8 fields terminated by ',' enclosed by '"' escaped by '\\' lines starting by 
'foo' terminated by '\r\n' ignore 1 lines (id, name, dept_id);
Query OK, 2 rows affected (1.19 sec)
Records: 2  Deleted: 0  Skipped: 0  Warnings: 0

mysql> select * from employee;
+----+------+---------+
| id | name | dept_id |
+----+------+---------+
|  1 | a"   |       0 |
|  3 | b    |       0 |
+----+------+---------+
2 rows in set (0.22 sec)

 第一行被ignore 1 lines忽略,第三行不包含'foo'而被忽略

你可能感兴趣的:(mysql,load,Data,infile)