📄 06-4.html
字号:
<P>
这个事实使得判断 <CODE>REPLACE</CODE> 是否是添加一条记录还是替换一条记录很容易:检查受影响记录行的值是 1 (添加)还是 2(替换)。
</P>
<P>
注意,除非你使用一个 <CODE>UNIQUE</CODE> 索引或 <CODE>PRIMARY KEY</CODE> ,使用 <CODE>REPLACE</CODE> 命令是没有感觉的,因为它会仅仅执行一个 <CODE>INSERT</CODE>。
</P>
<H3><A NAME="LOAD_DATA"></A>6.4.9 <CODE>LOAD DATA INFILE</CODE> 句法</H3>
<P>
<A NAME="IDX1442"></A>
</P>
<PRE>
LOAD DATA [LOW_PRIORITY | CONCURRENT] [LOCAL] INFILE 'file_name.txt'
[REPLACE | IGNORE]
INTO TABLE tbl_name
[FIELDS
[TERMINATED BY '\t']
[[OPTIONALLY] ENCLOSED BY '']
[ESCAPED BY '\\' ]
]
[LINES TERMINATED BY '\n']
[IGNORE number LINES]
[(col_name,...)]
</PRE>
<P>
<CODE>LOAD DATA INFILE</CODE> 语句以非常高的速度从一个文本文件中读取记录行并插入到一个表中。如果 <CODE>LOCAL</CODE> 关键词被指定,文件从客户端主机读取。如果 <CODE>LOCAL</CODE> 没有被指定,文件必须位于服务器上。(<CODE>LOCAL</CODE> 在 MySQL 3.22.6 或更新的版本中被支持。)
</P>
<P>
由于安全性的原因,当读取位于服务器端的文本文件时,文件必须处于数据库目录或可被所有人读取的地方。同时,为了对服务器端的文件使用 <CODE>LOAD DATA INFILE</CODE>,你必须在服务器主机上有 <CODE>FILE</CODE> 权限。查看章节 <A HREF="manual1.html#Privileges_provided">4.2.7 由 MySQL 提供的权限</A>。
</P>
<P>
在 MySQL 3.23.49 和 MySQL 4.0.2 中,只有当你没有以 <CODE>--local-infile=0</CODE> 选项启动 <CODE>mysqld</CODE>,或你没有禁止你的客户端程序支持 <CODE>LOCAL</CODE>的情况下,<CODE>LOCAL</CODE> 才会工作。查看章节 <A HREF="manual1.html#LOAD_DATA_LOCAL">4.2.4 LOAD DATA LOCAL 的安全性问题</A>.
</P>
<P>
如果你指定关键词 <CODE>LOW_PRIORITY</CODE>,<CODE>LOAD DATA</CODE> 语句的执行将会被延迟,直到没有其它的客户端正在读取表。
</P>
<P>
如果你对一个 <CODE>MyISAM</CODE> 表指定关键词 <CODE>CONCURRENT</CODE>,那么当 <CODE>LOAD DATA</CODE>正在执行时,其它的线程仍可以从表中检索数据。使用这个选项时,如果同时也有其它的线程正在使用表,这当然会有一点影响 <CODE>LOAD DATA</CODE> 的执行性能。
</P>
<P>
使用 <CODE>LOCAL</CODE> 将比让服务器直接访问文件要慢一些,因为文件的内容必须从客户端主机传送到服务器主机。而在另一方面,你不再需要有 <CODE>FILE</CODE> 权限用于装载本地文件。
</P>
<P>
如果你使用先于 MySQL 3.23.24 的版本,你不能够以 <CODE>LOAD DATA INFILE</CODE> 读取一个 FIFO 。如果你需要从一个 FIFO (例如,gunzip 的输出文件) 中读取,可以使用 <CODE>LOAD DATA LOCAL INFILE</CODE> 代替。
</P>
<P>
<A NAME="IDX1443"></A>
你也可以使用 <CODE>mysqlimport</CODE> 实用程序装载数据文件;它通过发送一个 <CODE>LOAD DATA INFILE</CODE> 命令到服务器来动作。<CODE>--local</CODE> 选项使得 <CODE>mysqlimport</CODE> 从客户端主机读取数据文件。如果客户端与服务器支持压缩协议,你可以指定 <CODE>--compress</CODE> 选项,以在较慢的网络中获得更好的性能。
</P>
<P>
当从服务器主机定位文件时,服务器使用下列规则:
</P>
<UL>
<LI>
如果给定一个完整的路径,服务器使用该路径名。
<LI>
如果给定一个有一个或多个前置构件的相对路径,服务器以相对服务器的数据目录搜索文件。
<LI>
如果给定一个没有前置构件的文件名,服务器从当前数据库的数据库目录搜寻文件。
</UL>
<P>
注意,这些规则意味着,一个以 <TT>`./myfile.txt'</TT> 给出的文件是从服务器的数据目录中读取的,然而,以 <TT>`myfile.txt'</TT> 给出的一个文件是从当前数据库的数据目录下读取的。举例来说,下面的 <CODE>LOAD DATA</CODE> 语句从 <CODE>db1</CODE> 数据库目录下读取文件 <TT>`data.txt'</TT>,因为 <CODE>db1</CODE> 是当前数据库,即使该语句明确地指定读取的文件被放入到 <CODE>db2</CODE> 数据库中的一个表中:
</P>
<PRE>
mysql> USE db1;
mysql> LOAD DATA INFILE "data.txt" INTO TABLE db2.my_table;
</PRE>
<P>
<CODE>REPLACE</CODE> 和 <CODE>IGNORE</CODE> 关键词控制对与现有的记录在唯一键值上重复的记录的处理。如果你指定 <CODE>REPLACE</CODE>,新的记录行将替换有相同唯一键值的现有记录行。如果你指定 <CODE>IGNORE</CODE>,将跳过与现有的记录行在唯一键值上重复的输入记录行。如果你没有指定任何一个选项,当重复键值出现时,将会发生一个错误,文本文件的剩余部分也将被忽略。
</P>
<P>
如果你使用 <CODE>LOCAL</CODE> 关键词从一个本地文件中读取数据,在此操作过程中,服务器没有办法停止文件的传送,因此缺省的处理方式就好像是 <CODE>IGNORE</CODE> 被指定一样。
</P>
<P>
如果你在一个空的 <CODE>MyISAM</CODE> 表上使用 <CODE>LOAD DATA INFILE</CODE>,所有非唯一索引会以一个分批方式被创建(就像 <CODE>REPAIR</CODE>)。当有许多索引时,这通常可以使 <CODE>LOAD DATA INFILE</CODE> 更快一些。
</P>
<P>
<CODE>LOAD DATA INFILE</CODE> 的 <CODE>SELECT ... INTO OUTFILE</CODE> 的逆操作。查看章节 <A HREF="06-4.html#SELECT">6.4.1 <CODE>SELECT</CODE> 句法</A>。
使用 <CODE>SELECT ... INTO OUTFILE</CODE> 将数据从一个数据库写到一个文件中。使用 <CODE>LOAD DATA INFILE</CODE> 读取文件到数据库中。两个命令的 <CODE>FIELDS</CODE> 和 <CODE>LINES</CODE> 子句的句法是一样的。两个子句都是可选的,但是如果两个同时被指定,<CODE>FIELDS</CODE> 子句必须出现在 <CODE>LINES</CODE> 子句之前。
</P>
<P>
如果你指定一个 <CODE>FIELDS</CODE> 子句,它的子句 (<CODE>TERMINATED BY</CODE>、<CODE>[OPTIONALLY] ENCLOSED
BY</CODE> 和 <CODE>ESCAPED BY</CODE>) 也是可选的,不过,你必须至少指定它们中的一个。
</P>
<P>
如果你没有指定一个 <CODE>FIELDS</CODE> 子句,缺省的相同于如果你这样写:
</P>
<PRE>
FIELDS TERMINATED BY '\t' ENCLOSED BY '' ESCAPED BY '\\'
</PRE>
<P>
如果你没有指定一个 <CODE>LINES</CODE> 子句,缺省的相同于如果你这样写:
</P>
<PRE>
LINES TERMINATED BY '\n'
</PRE>
<P>
换句话说,当读取输入时,缺省值导致 <CODE>LOAD DATA INFILE</CODE> 表现如下:
</P>
<UL>
<LI>
在换行符处寻找行的边界。
<LI>
在定位符处将行分开放到字段中。
<LI>
不认为字段由任何引号字符封装。
<LI>
将有 <SAMP>“\”</SAMP> 开头的定位符、换行符或 <SAMP>`\'</SAMP> 解释为字段值的一个文字字符。
</UL>
<P>
相反的,当写入输出时,缺省值导致 <CODE>SELECT ... INTO OUTFILE</CODE> 表现如下:
</P>
<UL>
<LI>
在字段值间加上定位符。
<LI>
不用任何引号字符封装字段。
<LI>
使用 <SAMP>“\”</SAMP> 转义出现在字段值中的定位符、换行符或 <SAMP>`\'</SAMP> 字符实例。
<LI>
在行的结尾处加上换行符。
</UL>
<P>
注意,为了写 <CODE>FIELDS ESCAPED BY '\\'</CODE>,你必须指定两个反斜线,该值会作为一个反斜线被读入。
</P>
<P>
<CODE>IGNORE number LINES</CODE> 选项可被用于忽略文件开头处的一个列名的头:
</P>
<PRE>
mysql> LOAD DATA INFILE "/tmp/file_name" INTO TABLE test IGNORE 1 LINES;
</PRE>
<P>
当你一前一后地使用 <CODE>SELECT ... INTO OUTFILE</CODE> 和 <CODE>LOAD DATA INFILE</CODE> 将数据从一个数据库写到一个文件中,然后再从文件中将它读入数据库中时,两个命令的字段和行处理选项必须匹配。否则,<CODE>LOAD DATA INFILE</CODE> 将不能正确地解释文件内容。假设你使用 <CODE>SELECT ... INTO OUTFILE</CODE> 以逗号分隔字段的方式将数据写入到一个文件中:
</P>
<PRE>
mysql> SELECT * INTO OUTFILE 'data.txt'
-> FIELDS TERMINATED BY ','
-> FROM ...;
</PRE>
<P>
为了将由逗号分隔的文件读回时,正确的语句应该是:
</P>
<PRE>
mysql> LOAD DATA INFILE 'data.txt' INTO TABLE table2
-> FIELDS TERMINATED BY ',';
</PRE>
<P>
如果你试图用下面所示的语句读取文件,它将不会工作,因为命令 <CODE>LOAD DATA INFILE</CODE> 以定位符区分字段值:
</P>
<PRE>
mysql> LOAD DATA INFILE 'data.txt' INTO TABLE table2
-> FIELDS TERMINATED BY '\t';
</PRE>
<P>
可能的结果是每个输入行将被解释为一个单独的字段。
</P>
<P>
<CODE>LOAD DATA INFILE</CODE> 也可以被用来读取从外部来源获得的文件。例如,dBASE 格式的文件,字段以逗号分隔并以双引号包围着。如果文件中的行以一个换行符终止,那么下面所示的可以说明你将用来装载文件的字段和行处理选项:
</P>
<PRE>
mysql> LOAD DATA INFILE 'data.txt' INTO TABLE tbl_name
-> FIELDS TERMINATED BY ',' ENCLOSED BY '"'
-> LINES TERMINATED BY '\n';
</PRE>
<P>
任何字段和行处理选项都可以指定一个空字符串(<CODE>''</CODE>)。如果不是空的,<CODE>FIELDS [OPTIONALLY] ENCLOSED BY</CODE> 和 <CODE>FIELDS ESCAPED BY</CODE> 值必须是一个单个字符。<CODE>FIELDS TERMINATED BY</CODE> 和 <CODE>LINES TERMINATED BY</CODE> 值可以超过一个字符。例如,为了写入由回车换行符终止的行,或读取包含这样的行的文件,应该指定一个 <CODE>LINES TERMINATED BY '\r\n'</CODE> 子句。
</P>
<P>
举例来说,为了读取一个文件到一个 SQL 表中,文件以一行 <CODE>%%</CODE> 分隔(开玩笑的),你可以这样做:
</P>
<PRE>
CREATE TABLE jokes (a INT NOT NULL AUTO_INCREMENT PRIMARY KEY, joke TEXT
NOT NULL);
LOAD DATA INFILE "/tmp/jokes.txt" INTO TABLE jokes FIELDS TERMINATED BY ""
LINES TERMINATED BY "\n%%\n" (joke);
</PRE>
<P>
<CODE>FIELDS [OPTIONALLY] ENCLOSED BY</CODE> 控制字段的包围字符。对于输出 (<CODE>SELECT ... INTO OUTFILE</CODE>),如果你省略单词 <CODE>OPTIONALLY</CODE>,所有的字段被 <CODE>ENCLOSED BY</CODE> 字符包围。这样的一个输出文件(以一个逗号作为字段分界符)示例如下:
</P>
<PRE>
"1","a string","100.20"
"2","a string containing a , comma","102.20"
"3","a string containing a \" quote","102.20"
"4","a string containing a \", quote and comma","102.20"
</PRE>
<P>
如果你指定 <CODE>OPTIONALLY</CODE>,<CODE>ENCLOSED BY</CODE> 字符仅被作用于包围 <CODE>CHAR</CODE> 和 <CODE>VARCHAR</CODE> 字段:
</P>
<PRE>
1,"a string",100.20
2,"a string containing a , comma",102.20
3,"a string containing a \" quote",102.20
4,"a string containing a \", quote and comma",102.20
</PRE>
<P>
注意,在一个字段值中出现的 <CODE>ENCLOSED BY</CODE> 字符,通过用 <CODE>ESCAPED BY</CODE> 字符作为其前缀对其转义。同时也要注意,如果你指定一个空的 <CODE>ESCAPED BY</CODE> 值,可能会产生不能被 <CODE>LOAD DATA INFILE</CODE> 正确读出的输出文件。例如,如果转义字符为空,上面显示的输出将变成如下显示的输出。请注意第四行的第二个字段,它包含一个逗号跟在一个引号后的两个字符,这(错误的)看起来像是一个字段的终止:
</P>
<PRE>
1,"a string",100.20
2,"a string containing a , comma",102.20
3,"a string containing a " quote",102.20
4,"a string containing a ", quote and comma",102.20
</PRE>
<P>
对于输入,<CODE>ENCLOSED BY</CODE> 字符如果存在,它将从字段值的尾部被剥离。(不管 <CODE>OPTIONALLY</CODE> 是否被指定,都是这样;对于输入解释,<CODE>OPTIONALLY</CODE> 不会影响它。) 由<CODE>ESCAPED BY</CODE> 字符领先于 <CODE>ENCLOSED BY</CODE> 字符的出现,将被解释为当前字段值的一部分。另外,在字段中出现的重复的 <CODE>ENCLOSED BY</CODE> 字符被解释为单个 <CODE>ENCLOSED BY</CODE> ,只要字段本身也是以该字符开始的。例如,如果 <CODE>ENCLOSED BY '"'</CODE> 被指定,引号将做如下处理:
</P>
<PRE>
"The ""BIG"" boss" -> The "BIG" boss
The "BIG" boss -> The "BIG" boss
The ""BIG"" boss -> The ""BIG"" boss
</PRE>
<P>
<CODE>FIELDS ESCAPED BY</CODE> 控制如何写入或读出特殊字符。如果 <CODE>FIELDS ESCAPED BY</CODE> 字符不是空的,它将被用于做为下列输出字符的前缀:
<UL>
<LI>
<CODE>FIELDS ESCAPED BY</CODE> 字符
<LI>
<CODE>FIELDS [OPTIONALLY] ENCLOSED BY</CODE> 字符
<LI>
<CODE>FIELDS TERMINATED BY</CODE> 和 <CODE>LINES TERMINATED BY</CODE> 值的第一个字符。
<LI>
ASCII <CODE>0</CODE> (实际上在转义字符后写上 ASCII <CODE>'0'</CODE>,而不是一个零值字节)
</UL>
<P>
如果 <CODE>FIELDS ESCAPED BY</CODE> 字符为空,没有字符被转义。指定一个空的转义字符可能不是一个好的主意,特别是如果你的数据字段值中包含刚才列表中的任何字符时。
</P>
<P>
对于输入,如果 <CODE>FIELDS ESCAPED BY</CODE> 字符不为空,该字符的出现将会被剥离,后续的字符在字面上做为字段值的一部分。除了一个转义
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -