所有使用的关键词必须严格以上面所显示的次序被给出。举例来说,一个 HAVING 子句必须出现在 GROUP BY 子句后,在 ORDER BY 字句之前。
* 一个 SELECT 表达式可以使用 AS 指定一个别名。别名可以当作表达式的列名,用于 ORDER BY 或 HAVING 子句中。例如:
mysql> SELECT CONCAT(last_name,', ',first_name) AS full_name FROM mytable ORDER BY full_name;
* 在一个 WHERE 子句中使用一个列别名是不允许的,因为,当 WHERE 子句被执行时,列值可能还没有被计算确定。查看章节 A.5.4 使用 alias 的限制。
* FROM table_references 子句表示从哪个表中检索记录行。如果你命名超过超过一个表,并执行一个 join。对于 join 句法的信息,查看章节 6.4.1.1 JOIN 句法。对于每个引用的表,你可以顺便指定一个别名。
table_name [[AS] alias] [[USE INDEX (key_list)] | [IGNORE INDEX (key_list)] | FORCE INDEX (key_list)]]
到 MySQL 3.23.12 时,当 MySQL 在从一个表中检索信息时,你可以提示它选择了哪一个索引。如果 EXPLAIN 显示 MySQL 使用了可能的索引列表中错误的索引,这个特性将是很有用的。通过指定 USE INDEX (key_list),你可以告诉 MySQL 使用可能的索引中最合适的一个索引在表中查找记录行。可选的二选一句法 IGNORE INDEX (key_list) 可被用于告诉 MySQL 不使用特定的索引。 在 MySQL 4.0.9 中,你也可以使用 FORCE INDEX。这个有点像 USE INDEX (key_list),但是有了这个附加物,一个表的扫描被采用时,将会有非常大的开销。换句法说,如果没有方法使用给定的索引在表中寻找记录行,这时表扫描才会被使用。 USE/IGNORE/FORCE KEY 分别是 USE/IGNORE/FORCE INDEX 的同义词。
mysql> SELECT t1.name, t2.salary FROM employee AS t1, info AS t2 -> WHERE t1.name = t2.name; mysql> SELECT t1.name, t2.salary FROM employee t1, info t2 -> WHERE t1.name = t2.name;
* 选取出来用于输出的列可以在 ORDER BY 和 GROUP BY 子句中使用列名、列的别名或列的位置来引用。列的位置从 1 开始:
mysql> SELECT college, region, seed FROM tournament -> ORDER BY region, seed; mysql> SELECT college, region AS r, seed AS s FROM tournament -> ORDER BY r, s; mysql> SELECT college, region, seed FROM tournament -> ORDER BY 2, 3;
为了以倒序排序,可以在 ORDER BY 子句中用于排序的列名后添加一个 DESC (递减 descending)关键词。缺省为升序排序;这也可以通过使用 ASC 关键词明确指定。
* 在 WHERE 子句中可以使用 MySQL 支持的任何函数。查看章节 6.3 用于 SELECT 和 WHERE 子句的函数。
* HAVING 子句可以引用任何列或在 select_expression 中命名的别名。它在最后被执行,仅仅就在项目被送到客户端之前,不进行任何优化。所以不要对应该放在 WHERE 子句中的项目使用 HAVING。举例来说,不要写成这样:
mysql> SELECT col_name FROM tbl_name HAVING col_name > 0;
用这个代替:
mysql> SELECT col_name FROM tbl_name WHERE col_name > 0;
在 MySQL 3.22.5 或以后的版本中,你也可以这下面的形式书写一个查询:
mysql> SELECT user,MAX(salary) FROM users -> GROUP BY user HAVING MAX(salary)>10;
在较早的 MySQL 版本中,你可能需要用下面的代替了:
mysql> SELECT user,MAX(salary) AS sum FROM users -> group by user HAVING sum>10;
* DISTINCT、DISTINCTROW 和 ALL 选项指定重复的记录行是否被返回。缺省为 (ALL),返回所有匹配的记录行。DISTINCT 和 DISTINCTROW 是同义词,它指定结果集重复的记录行被排除。
mysql> SELECT * FROM table LIMIT 5,10; # 检索记录行 6-15
为了检索从某一个偏移量到记录集的结束所有的记录行,可以指定第二个参数为 -1:
mysql> SELECT * FROM table LIMIT 95,-1; # 检索记录行 96-last.
如果只给定一个参数,它表示返回最大的记录行数目:
mysql> SELECT * FROM table LIMIT 5; # 检索前 5 个记录行
换句话说,LIMIT n 等价于 LIMIT 0,n。
* SELECT ... INTO OUTFILE 'file_name' 格式的 SELECT 将选择的记录行写入一个文件。文件被建立在服务器主机上,并且不可以是已存在的 (不管别的,这可以防止数据库表和文件例如 `/etc/passwd' 被破坏)。你必须在服务器主机上有 FILE 权限来使用这个形式的 SELECT。 SELECT ... INTO OUTFILE 主要是有意于让你能够在服务主机上快速地转储一个表。如果你希望将结果文件建立在其它的主机上,而不是服务器上,你就不能使用 SELECT ... INTO OUTFILE。在这种情况下,你应该使用某些客户端程序例如 mysqldump --tab 或 mysql -e "SELECT ..." > outfile 产生文件来代替它。 SELECT ... INTO OUTFILE 是 LOAD DATA INFILE 的逆操作;语句中的 export_options 部分的句法由 FIELDS 和 LINES 子句组成,它们与与用在 LOAD DATA INFILE 语句中的相同。查看章节 6.4.9 LOAD DATA INFILE 句法。 在结果文本文件中,只有下列的字符被 ESCAPED BY 指定的字符转义: o ESCAPED BY 字符 o 在 FIELDS TERMINATED BY 中的第一个字符 o 在 LINES TERMINATED BY 中的第一个字符 另外,ASCII 0 被转换到 ESCAPED BY 后而跟一个 0 (ASCII 48)。 上述行为的原因是,你必须 转义任何 FIELDS TERMINATED BY、ESCAPED BY 或LINES TERMINATED BY 字符,以便能可靠地将文件读回。ASCII 0 被转义是为了更容易地使用某些分页程序查看它。 因为结果文件并不需要遵从 SQL 句法,所以其它是不需要转义。 下面的例子得到的文件是可用于许多老程序的格式。
SELECT a,b,a+b INTO OUTFILE "/tmp/result.text" FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"' LINES TERMINATED BY "\n" FROM test_table;
* 如果使用 INTO DUMPFILE 代替 INTO OUTFILE,MySQL 将在文件中只写一行,没任何列或行端接和任何转义。如果你希望存储一个 blob 列到文件中,这是非常有用的。 * 注意,任何由 INTO OUTFILE 和 INTO DUMPFILE 创建的文件将被所有用户可读写!原因是, MySQL 服务器不能够创建一个其他用户拥有的文件,(你决不应该以 root 身份运行 mysqld),该文件必须是公共可读写的,以便于你能操作它。
* 如果你以页/行锁使用在一个存储引擎上 FOR UPDATE,被检索的记录行将被写锁。
6.4.1.1 JOIN 句法
MySQL 支持在 SELECT 中使用下面所示的 JOIN 句法:
table_reference, table_reference table_reference [CROSS] JOIN table_reference table_reference INNER JOIN table_reference join_condition table_reference STRAIGHT_JOIN table_reference table_reference LEFT [OUTER] JOIN table_reference join_condition table_reference LEFT [OUTER] JOIN table_reference table_reference NATURAL [LEFT [OUTER]] JOIN table_reference { OJ table_reference LEFT OUTER JOIN table_reference ON conditional_expr } table_reference RIGHT [OUTER] JOIN table_reference join_condition table_reference RIGHT [OUTER] JOIN table_reference table_reference NATURAL [RIGHT [OUTER]] JOIN table_reference
table_reference 定义如下:
table_name [[AS] alias] [[USE INDEX (key_list)] | [IGNORE INDEX (key_list)] | [FORCE INDEX (key_list)]]
join_condition 定义如下:
ON conditional_expr | USING (column_list)
通常不应该在 ON 存在任何条件式,它是用于限制在结果集中有哪个行的(对于这个规则也有例外)。如果你希望哪个记录行应该在结果中,你必须在 WHERE 子句中限制它。
* 一个表引用可以使用 tbl_name AS alias_name 或 tbl_name alias_name 命以别名:
mysql> SELECT t1.name, t2.salary FROM employee AS t1, info AS t2 -> WHERE t1.name = t2.name;
* ON 条件是可以用在一个 WHERE 子句中的任何形式的条件。
* 如果在一个 LEFT JOIN 的 ON 或 USING 部分中右表没有匹配的记录,一个所有列被设置为 NULL 的记录行将被用于右表。你可以通过这个行为找到一个表在另一个表中没有配对物的记录:
mysql> SELECT table1.* FROM table1 -> LEFT JOIN table2 ON table1.id=table2.id -> WHERE table2.id IS NULL;
这个例子在 table1 中找到所有的记录行,其 id 值没有出现在 table2 中(即,所有在 table1 存在的,但在 table2 中没有对应记录的记录行)。当然,这是假定 table2.id 被声明为 NOT NULL 的。查看章节 5.2.6 MySQL 如何优化 LEFT JOIN 和 RIGHT JOIN。
* USING (column_list) 子句指定了一个列的列表,列表的中列必须同时存在于两个表中。例如 USING 子句如下所示:
A LEFT JOIN B USING (C1,C2,C3,...)
它可以被定义为在语义上等同于一个这样的 ON 表达式:
A.C1=B.C1 AND A.C2=B.C2 AND A.C3=B.C3,...
* 两个表的 NATURAL [LEFT] JOIN 被定义为在语义上等同于使用了 USING 子句指定存在于两张表中的所有列的一个 INNER JOIN 或一个 LEFT JOIN。
* INNER JOIN 和 , (逗号) 在语义上是等同的。都是在所有的表之间进行一个全联结。通常,在 WHERE 条件中指定表应该如何联结。
* RIGHT JOIN 作用类似于 LEFT JOIN。为了保持数据库边的代码上精简,LEFT JOIN 被推荐使用来代替 RIGHT JOIN。
* 到 MySQL 3.23.12 时,当 MySQL 在从一个表中检索信息时,你可以提示它选择了哪一个索引。如果 EXPLAIN 显示 MySQL 使用了可能的索引列表中错误的索引,这个特性将是很有用的。通过指定 USE INDEX (key_list),你可以告诉 MySQL 使用可能的索引中最合适的一个索引在表中查找记录行。可选的二选一句法 IGNORE INDEX (key_list) 可被用于告诉 MySQL 不使用特定的索引。 在 MySQL 4.0.9 中,你也可以使用 FORCE INDEX。这个有点像 USE INDEX (key_list),但是有了这个附加物,一个表的扫描被采用时,将会有非常大的开销。换句法说,如果没有方法使用给定的索引在表中寻找记录行,这时表扫描才会被使用。 USE/IGNORE/FORCE KEY 分别是 USE/IGNORE/FORCE INDEX 的同义词。
一些例子:
mysql> SELECT * FROM table1,table2 WHERE table1.id=table2.id; mysql> SELECT * FROM table1 LEFT JOIN table2 ON table1.id=table2.id; mysql> SELECT * FROM table1 LEFT JOIN table2 USING (id); mysql> SELECT * FROM table1 LEFT JOIN table2 ON table1.id=table2.id -> LEFT JOIN table3 ON table2.id=table3.id; mysql> SELECT * FROM table1 USE INDEX (key1,key2) -> WHERE key1=1 AND key2=2 AND key3=3; mysql> SELECT * FROM table1 IGNORE INDEX (key3) -> WHERE key1=1 AND key2=2 AND key3=3;
查看章节 5.2.6 MySQL 如何优化 LEFT JOIN 和 RIGHT JOIN。 6.4.1.2 UNION 句法
SELECT ... UNION [ALL] SELECT ... [UNION SELECT ...]
如果你不为 UNION 使用关键词 ALL,所有返回的记录行将是唯一的,就好像你为整个返回集使用了一个 DISTINCT。如果你指定了 ALL,那么你将得到从所有使用的 SELECT 语句中返回的所有匹配记录行。
如果你希望对整个 UNION 结果使用一个 ORDER BY,你应该使用圆括号:
(SELECT a FROM table_name WHERE a=10 AND B=1 ORDER BY a LIMIT 10) UNION (SELECT a FROM table_name WHERE a=11 AND B=2 ORDER BY a LIMIT 10) ORDER BY a;
6.4.2 HANDLER 句法
HANDLER tbl_name OPEN [ AS alias ] HANDLER tbl_name READ index_name { = | >= | <= | < } (value1,value2,...) [ WHERE ... ] [LIMIT ... ] HANDLER tbl_name READ index_name { FIRST | NEXT | PREV | LAST } [ WHERE ... ] [LIMIT ... ] HANDLER tbl_name READ { FIRST | NEXT } [ WHERE ... ] [LIMIT ... ] HANDLER tbl_name CLOSE
HANDLER 语句提供了直接访问 MyISAM 表存储引擎的接口。
HANDLER 语句的第一个形式打开一个表,通过后来的 HANDLER ... READ 语句使它可读取。这个表对象将不能被其它线程共享,也不会被关闭,除非线程调用 HANDLER tbl_name CLOSE 或线程关闭。
第二个形式读取指定的索引遵从那个条件并且适合 WHERE 条件的一行(或更多的,由 LIMIT 子句指定)。如果索引由几个部分组成(范围有几个列),值以逗号分隔的列表指定;如果只提供的一部分值,那么第一个列是必需的。
第三个形式从表中以索引的顺序读取匹配 WHERE 条件的一行(或更多的,由 LIMIT 子句指定)。
第四个形式(没有索引清单)从表中以自然的列顺序(在数据文件中存储的次序)读取匹配 WHERE 条件的一行(或更多的,由 LIMIT 子句指定)。如果期望做一个全表扫描,它将比 HANDLER tbl_name READ index_name 更快。
HANDLER ... CLOSE 关闭一个以 HANDLER ... OPEN 打开的表。
HANDLER 是一个稍微低级的语句。举例来说,它不提供一致性约束。更确切地说,HANDLER ... OPEN 不 接受一个表的快照,并且 不 锁定表。这就意味着在一个 HANDLER ... OPEN 被执行后,表数据仍会被 (这个或其它的线程) 修改,这些修改可能在 HANDLER ... NEXT 和 HANDLER ... PREV 扫描中才会部分地出现。
使用这个接口代替普通 SQL 的原因是:
* 它比 SELECT 快,因为: o 在 HANDLER OPEN 中,一个指定的存储引擎被分配给当前线程。 o 较少的复杂解析。 o 没有优化器和没有查询检查开销。 o 在两个处理请求之间不需要锁定使用的表。 o 接口处理机并不提供一个一致性的查看数据 (举例来说,读污染 dirty-reads 是允许的),因而,存储引擎可以做 SQL 通常不允许的优化。 * 它使得更加容易地移植一个使用对 MySQL 的 ISAM 类似接口的应用程序。 * 它允许你在一个以 SQL 不容易完成(在某些不可能的完全)的情况下遍历一个数据库。当使用提供了一个交互式的用户接口访问数据库的应用程序时,接口处理机是更加自然的查看数据的方式。
INSERT 语句的 DELAYED 选项是一个 MySQL 特有的选项,如果你的客户端不能等待 INSERT 的完成,这将会是很有用的。This is a common problem when you use MySQL for logging and 当你打开日志记录使用 MySQL 并且你周期性的需花费很长时间才完成的 SELECT 和 UPDATE 语句时,这将是一个很普遍的问题。DELAYED 在 MySQL 3.22.15 中被引入。它是 MySQL 对 ANSI SQL92 的一个扩展。
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,...)]
LOAD DATA INFILE 语句以非常高的速度从一个文本文件中读取记录行并插入到一个表中。如果 LOCAL 关键词被指定,文件从客户端主机读取。如果 LOCAL 没有被指定,文件必须位于服务器上。(LOCAL 在 MySQL 3.22.6 或更新的版本中被支持。)
由于安全性的原因,当读取位于服务器端的文本文件时,文件必须处于数据库目录或可被所有人读取的地方。同时,为了对服务器端的文件使用 LOAD DATA INFILE,你必须在服务器主机上有 FILE 权限。查看章节 4.2.7 由 MySQL 提供的权限。
在 MySQL 3.23.49 和 MySQL 4.0.2 中,只有当你没有以 --local-infile=0 选项启动 mysqld,或你没有禁止你的客户端程序支持 LOCAL的情况下,LOCAL 才会工作。查看章节 4.2.4 LOAD DATA LOCAL 的安全性问题.
如果你指定关键词 LOW_PRIORITY,LOAD DATA 语句的执行将会被延迟,直到没有其它的客户端正在读取表。
如果你对一个 MyISAM 表指定关键词 CONCURRENT,那么当 LOAD DATA正在执行时,其它的线程仍可以从表中检索数据。使用这个选项时,如果同时也有其它的线程正在使用表,这当然会有一点影响 LOAD DATA 的执行性能。
使用 LOCAL 将比让服务器直接访问文件要慢一些,因为文件的内容必须从客户端主机传送到服务器主机。而在另一方面,你不再需要有 FILE 权限用于装载本地文件。
如果你使用先于 MySQL 3.23.24 的版本,你不能够以 LOAD DATA INFILE 读取一个 FIFO 。如果你需要从一个 FIFO (例如,gunzip 的输出文件) 中读取,可以使用 LOAD DATA LOCAL INFILE 代替。
注意,为了写 FIELDS ESCAPED BY '\',你必须指定两个反斜线,该值会作为一个反斜线被读入。
IGNORE number LINES 选项可被用于忽略文件开头处的一个列名的头:
mysql> LOAD DATA INFILE "/tmp/file_name" INTO TABLE test IGNORE 1 LINES;
当你一前一后地使用 SELECT ... INTO OUTFILE 和 LOAD DATA INFILE 将数据从一个数据库写到一个文件中,然后再从文件中将它读入数据库中时,两个命令的字段和行处理选项必须匹配。否则,LOAD DATA INFILE 将不能正确地解释文件内容。假设你使用 SELECT ... INTO OUTFILE 以逗号分隔字段的方式将数据写入到一个文件中:
mysql> SELECT * INTO OUTFILE 'data.txt' -> FIELDS TERMINATED BY ',' -> FROM ...;
为了将由逗号分隔的文件读回时,正确的语句应该是:
mysql> LOAD DATA INFILE 'data.txt' INTO TABLE table2 -> FIELDS TERMINATED BY ',';
如果你试图用下面所示的语句读取文件,它将不会工作,因为命令 LOAD DATA INFILE 以定位符区分字段值:
mysql> LOAD DATA INFILE 'data.txt' INTO TABLE table2 -> FIELDS TERMINATED BY '\t';
可能的结果是每个输入行将被解释为一个单独的字段。
LOAD DATA INFILE 也可以被用来读取从外部来源获得的文件。例如,dBASE 格式的文件,字段以逗号分隔并以双引号包围着。如果文件中的行以一个换行符终止,那么下面所示的可以说明你将用来装载文件的字段和行处理选项:
mysql> LOAD DATA INFILE 'data.txt' INTO TABLE tbl_name -> FIELDS TERMINATED BY ',' ENCLOSED BY '"' -> LINES TERMINATED BY '\n';
任何字段和行处理选项都可以指定一个空字符串('')。如果不是空的,FIELDS [OPTIONALLY] ENCLOSED BY 和 FIELDS ESCAPED BY 值必须是一个单个字符。FIELDS TERMINATED BY 和 LINES TERMINATED BY 值可以超过一个字符。例如,为了写入由回车换行符终止的行,或读取包含这样的行的文件,应该指定一个 LINES TERMINATED BY '\r\n' 子句。
举例来说,为了读取一个文件到一个 SQL 表中,文件以一行 %% 分隔(开玩笑的),你可以这样做:
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);
FIELDS [OPTIONALLY] ENCLOSED BY 控制字段的包围字符。对于输出 (SELECT ... INTO OUTFILE),如果你省略单词 OPTIONALLY,所有的字段被 ENCLOSED BY 字符包围。这样的一个输出文件(以一个逗号作为字段分界符)示例如下:
"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"
如果你指定 OPTIONALLY,ENCLOSED BY 字符仅被作用于包围 CHAR 和 VARCHAR 字段:
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
注意,在一个字段值中出现的 ENCLOSED BY 字符,通过用 ESCAPED BY 字符作为其前缀对其转义。同时也要注意,如果你指定一个空的 ESCAPED BY 值,可能会产生不能被 LOAD DATA INFILE 正确读出的输出文件。例如,如果转义字符为空,上面显示的输出将变成如下显示的输出。请注意第四行的第二个字段,它包含一个逗号跟在一个引号后的两个字符,这(错误的)看起来像是一个字段的终止:
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
对于输入,ENCLOSED BY 字符如果存在,它将从字段值的尾部被剥离。(不管 OPTIONALLY 是否被指定,都是这样;对于输入解释,OPTIONALLY 不会影响它。) 由ESCAPED BY 字符领先于 ENCLOSED BY 字符的出现,将被解释为当前字段值的一部分。另外,在字段中出现的重复的 ENCLOSED BY 字符被解释为单个 ENCLOSED BY ,只要字段本身也是以该字符开始的。例如,如果 ENCLOSED BY '"' 被指定,引号将做如下处理:
"The ""BIG"" boss" -> The "BIG" boss The "BIG" boss -> The "BIG" boss The ""BIG"" boss -> The ""BIG"" boss
FIELDS ESCAPED BY 控制如何写入或读出特殊字符。如果 FIELDS ESCAPED BY 字符不是空的,它将被用于做为下列输出字符的前缀:
* FIELDS ESCAPED BY 字符 * FIELDS [OPTIONALLY] ENCLOSED BY 字符 * FIELDS TERMINATED BY 和 LINES TERMINATED BY 值的第一个字符。 * ASCII 0 (实际上在转义字符后写上 ASCII '0',而不是一个零值字节)
如果 FIELDS ESCAPED BY 字符为空,没有字符被转义。指定一个空的转义字符可能不是一个好的主意,特别是如果你的数据字段值中包含刚才列表中的任何字符时。
* 如果 LINES TERMINATED BY 是一个空字符串,FIELDS TERMINATED BY 是非空的,行也用 FIELDS TERMINATED BY 终止。 * 如果 FIELDS TERMINATED BY 和 FIELDS ENCLOSED BY 值都是空的 (''),一个固定行(无定界符) 格式被使用。用固定行格式时,在字段之间不使用分隔符。代替的,列值的写入和读取使用列的“显示”宽度。例如,如果一个列被定义为 INT(7),列的值将使用 7 个字符的字段被写入。对于输入,列值通过读取 7 个字符来获得。固定行格式也影响对 NULL 值的处理;见下面。注意,如果你正在使用一个多字节的字符集,固定长度格式将不能工作。
NULL 值的处理有很多,取决于你所使用的 FIELDS 和 LINES 选项:
* 对于缺省的 FIELDS 和 LINES 值,输出时,NULL 被写成 \N,当读入时,\N 被作为 NULL 读入(假设 ESCAPED BY 字符为 “\”)。 * 如果 FIELDS ENCLOSED BY 是非空的,一个字段包含文字词 NULL 的,它的值做为一个 NULL 值被读入 (这不同于被 FIELDS ENCLOSED BY 包围的词 NULL,它是被作为 'NULL' 读入的)。 * 如果 FIELDS ESCAPED BY 是空的,NULL 值被写为词 NULL。 * 用固定行格式时 (它发生于 FIELDS TERMINATED BY 和 FIELDS ENCLOSED BY 两者均为空),NULL 被写为一个空的字符串。注意,当将表中的 NULL 值和空字符串一起写到文件中时,它们将被混淆,因为它们都是作为空字符串被写入的。如果你在文件时,需要对他们两个进行区分,你不应该使用固定行格式。
一些不能被 LOAD DATA INFILE 支持的情况:
* 固定尺寸的记录行 (FIELDS TERMINATED BY 和 FIELDS ENCLOSED BY 均为空) 和 BLOB 或 TEXT 列。 * 如果你指定一个分隔符与另一个相同,或是另一个的前缀,LOAD DATA INFILE 可能会不能正确地解释输入。例如,下列的 FIELDS 子句将会产生问题:
FIELDS TERMINATED BY '"' ENCLOSED BY '"'
* 如果 FIELDS ESCAPED BY 为空,一个字段值中包含有 FIELDS ENCLOSED BY 或 LINES TERMINATED BY 被 FIELDS TERMINATED BY 跟随的值时,将会引起 LOAD DATA INFILE 过早地停止读取一个字段或一行。这是因为 LOAD DATA INFILE 不能够正确地决定字段或行值在哪里结果。
下面的例子将装载 persondata 表的所有列:
mysql> LOAD DATA INFILE 'persondata.txt' INTO TABLE persondata;
没有字段列被指定,因而 LOAD DATA INFILE 认为输入行包含表列中所有的字段。使用缺省的 FIELDS 和 LINES 值。
如果你希望装载表中的某些列,那指定一个字段列表:
mysql> LOAD DATA INFILE 'persondata.txt' -> INTO TABLE persondata (col1,col2,...);
如果输入文件的字段次序不同于表中列的顺序,你也必须指定一个字段列表。否则 MySQL 不知道如何将输入字段与表中的列匹配。