当前位置:嗨网首页>书籍在线阅读

12-导出

  
选择背景色: 黄橙 洋红 淡粉 水蓝 草绿 白色 选择字体: 宋体 黑体 微软雅黑 楷体 选择字体大小: 恢复默认

在某些情况下,为了一些特定的目的,经常需要将表里的数据导出为某些符号分割的纯数据文本,而不是SQL语句。这些应用可能有以下一些:

用来作为EXCEL显示;

单纯为了节省备份空间;

为了快速地加载数据,LOAD DATA的加载速度比普通的SQL加载要快 20倍以上。为了满足这些应用,可以使用以下两种办法来实现。

1.方法1

使用SELECT ...INTO OUTFILE ...命令来导出数据,具体语法如下。

mysql> SELECT* FROM tablename INTO OUTFILE 'target_file' [option];

其中option参数可以是以下选项:

FIELDS TERMINATED BY 'string'(字段分隔符,默认为制表符'\t');

FIELDS [OPTIONALLY] ENCLOSED BY 'char'(字段引用符,如果加OPTIONALLY选项则只用在char、varchar和text等字符型字段上。默认不使用引用符);

FIELDS ESCAPED BY 'char'(转义字符,默认为'\');

LINES STARTING BY 'string'(每行前都加此字符串,默认'');

LINES TERMINATED BY 'string'(行结束符,默认为'\n');

其中char表示此符号只能是单个字符,string表示可以是字符串。

例如,将emp表中数据导出为数据文本,其中,字段分隔符为“,”,字段引用符为“"”(双引号),记录结束符为回车符,具体实现如下:

mysql> select * from emp into outfile '/tmp/emp.txt' fields terminated by "," enclosed by '"' ;

Query OK, 5 rows affected (0.00 sec)

mysql>

mysql> system more /tmp/emp.txt

"1","z1","aa"

"2","z1","aa"

"3","z1","aa"

"4","z1","aa"

"1","z1","aa"

发现第一列是数值型,如果不希望字段两边用引号引起,则语句改为:

mysql> select * from emp into outfile '/tmp/emp.txt' fields terminated by "," optionally enclosed by '"' ;

Query OK, 5 rows affected (0.00 sec)

mysql> system more /tmp/emp.txt

1,"z1","aa"

2,"z1","aa"

3,"z1","aa"

4,"z1","aa"

1,"z1","aa"

结果如我们所愿,第一列的双引号被去掉。

下面来测试一下转义字符。转义字符,顾名思义,就是由于含义模糊而需要特殊进行转换的字符,在不同的情况下,需要转义的字符是不一样的。MySQL 导出的数据中需要转义的字符主要包括以下3类:

转义字符本身;

字段分隔符;

记录分隔符。

在下面的例子中,对表emp中的name更新为含以上三类字符的字符串,然后导出:

mysql> update emp set name='\"##!aa' where id=1;

Query OK, 2 rows affected (0.04 sec)

Rows matched: 2 Changed: 2 Warnings: 0

mysql> system rm /tmp/emp.txt

mysql> select * from emp into outfile '/tmp/emp.txt' fields terminated by "," optionally enclosed by '"' ;

Query OK, 5 rows affected (0.00 sec)

mysql> system more /tmp/emp.txt

1,"\\"##!aa","aa"

2,"z1","aa"

3,"z1","aa"

4,"z1","aa"

1,"\\"##!aa","aa"

mysql>

以上例子中,name 中含有转义字符本身“\”和域引用符“"”,因此,在输出的数据中我们发现这两种字符前面都加上了转义字符“\”,“#”变成了“\#”。继续进行测试,将id为1的name更新为含有字段分隔符“,”的字符串:

mysql> update emp set name='\"#,#,!aa' where id=1;

Query OK, 2 rows affected (0.04 sec)

Rows matched: 2 Changed: 2 Warnings: 0

mysql> system rm /tmp/emp.txt

mysql> select * from emp into outfile '/tmp/emp.txt' fields terminated by "," optionally enclosed by '"' ;

Query OK, 5 rows affected (0.00 sec)

mysql> system more /tmp/emp.txt

1,"\\"#,#,!aa","aa"

2,"z1","aa"

3,"z1","aa"

4,"z1","aa"

1,"\\"#,#,!aa","aa"

注意:在MySQL客户端连接成功后,如果要执行操作系统的命令,那么可以用“system+操作系统命令”来进行执行。

这个时候,发现数据中的字符“,”并没有被转义,这是为什么呢?其实仔细想想就明白了,因为每个字符串的两边带有引用符“"”(双引号),所以当MySQL看到数据中的“,”时,由于它处在前半个引用分隔符之后,后半个引用分隔符之前,所以并没有将它作为字段分隔符,而只是作为普通的一个数据字符来对待,因而不需要转义。继续做测试,将输出文件的字段引用符去掉,这个时候,我们的预期是数据中的“,”将成为转义字符而需要加上“\”:

mysql> system rm /tmp/emp.txt

mysql> select * from emp into outfile '/tmp/emp.txt' fields terminated by "," ;

Query OK, 5 rows affected (0.00 sec)

mysql> system more /tmp/emp.txt

1,\"#\,#\,!aa,aa

2,z1,aa

3,z1,aa

4,z1,aa

1,\"#\,#\,!aa,aa

果然,现在的“,”前面加上了转义字符“\”。而刚才的引用符“"”却没有被转义,因为它已经没有什么歧义,不需要被转义。

通过上面的测试,可以得出以下结论:

当导出命令中包含字段引用符时,数据中含有转义字符本身和字段引用符的字符需要被转义;

当导出命令中不包含字段引用符时,数据中含有转义字符本身和字段分隔符的字符需要被转义。

注意:SELECT…INTO OUTFILE...产生的输出文件如果在目标目录下有重名文件,将不会创建成功,源文件不能被自动覆盖。

2.方法2

使用mysqldump导出数据为文本的具体语法如下。

mysqldump –u username –T target_dir dbname tablename [option]

其中option参数可以是以下选项:

--fields-terminated-by=name(字段分隔符);

--fields-enclosed-by=name(字段引用符);

--fields-optionally-enclosed-by=name(字段引用符,只用在char、varchar和text等字符型字段上);

--fields-escaped-by=name(转义字符);

--lines-terminated-by=name(记录结束符)。

下面的例子中,采用mysqldump生成了指定分隔符分隔的文本:

[root@localhost tmp]# mysqldump -uroot -T /tmp test emp --fields-terminated-by ','--fields-optionally-enclosed-by '"'

[root@localhost tmp]# more /tmp/emp.txt

1,"\\"#,#,!aa","aa"

2,"z1","aa"

3,"z1","aa"

4,"z1","aa"

1,"\\"#,#,!aa","aa"

除了生成数据文件emp.txt之外,还生成一个emp.sql文件,里面记录了emp表的创建脚本,记录的内容如下:

[root@localhost tmp]# more emp.sql

-- MySQL dump 10.11

--

-- Host: localhost Database: test


-- Server version 5.0.41-community-log

/!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT /;

/!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS /;

/!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION /;

/!40101 SET NAMES utf8 /;

/!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE /;

/!40103 SET TIME_ZONE='+00:00' /;

/!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='' /;

/!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 /;

--

-- Table structure for table 'emp'

--

DROP TABLE IF EXISTS 'emp';

CREATE TABLE 'emp' (

'id' int(11) default NULL,

'name' varchar(10) default NULL,

'content' text

) ENGINE=InnoDB DEFAULT CHARSET=latin1;

/!40103 SET TIME_ZONE=@OLD_TIME_ZONE /;

/!40101 SET SQL_MODE=@OLD_SQL_MODE /;

/!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT /;

/!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS /;

/!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION /;

/!40111 SET SQL_NOTES=@OLD_SQL_NOTES /;

-- Dump completed on 2007-08-11 20:27:32

可以发现,除多了一个表的创建脚本文件外,mysqldump和SELEC…INTO OUTFILE…的选项和语法非常类似。其实,mysqldump实际调用的就是后者提供的接口,并在其上面添加了一些新的功能而已。