我想用过 PostgreSQL 的朋友大多知道 copy 命令,使用 copy 命令导入,导出数据很高效,但用过 \copy 元子命令的朋友可能不多,今天简单介绍下两者的区别和使用场景。
copy 命令属于 SQL 命令,执行时仅会在数据库服务端查找文件,如果需要将文件数据导入到表或导出表数据到文件时须以超级用户执行,而 \copy 为元子命令,任何 psql 客户端登录数据库成功后都可以从客户端导入导出数据。
关于 copy 命令
Name
COPY – copy data between a file and a table
Synopsis
COPY table_name [ ( column_name [, …] ) ]
FROM { ‘filename’ | PROGRAM ‘command’ | STDIN }
[ [ WITH ] ( option [, …] ) ]
COPY { table_name [ ( column_name [, …] ) ] | ( query ) }
TO { ‘filename’ | PROGRAM ‘command’ | STDOUT }
[ [ WITH ] ( option [, …] ) ]
where option can be one of:
FORMAT format_name
OIDS [ boolean ]
FREEZE [ boolean ]
DELIMITER ‘delimiter_character’
NULL ‘null_string’
HEADER [ boolean ]
QUOTE ‘quote_character’
ESCAPE ‘escape_character’
FORCE_QUOTE { ( column_name [, …] ) | * }
FORCE_NOT_NULL ( column_name [, …] )
ENCODING ‘encoding_name’
备注:上面是 copy 命令的用法,供查阅,这里不详细介绍,接下来测试下。
copy 和 \copy 测试场景
数据库: 192.168.2.36/1925 库名:francs
客户端: ubuntu 笔记本桌面
目标: 将ubuntu 本地文件导入数据库中的表 test_copy
2.1 服务端创建测试表1
2
3
4
5[pg93@redhatB ~]$ psql francs francs
psql (9.3.0)
Type "help" for help.
francs=> create table test_copy(id int4,name character varying(32));
CREATE TABLE
2.2 客户端创建数据文件1
2
3
4francs@francs:~/script/tf$ cat test_copy.txt
1 a
2 b
3 c
2.3 在客户端将数据文件导入表 test_copy 中1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18francs@francs:~/script/tf$ psql -h 192.168.2.36 -p 1925 francs francs
用户 francs 的口令:
psql (9.3.2, 服务器 9.3.0)
输入 "help" 来获取帮助信息.
francs=> \! cat '/home/francs/script/tf/test_copy.txt';
1 a
2 b
3 c
francs=> \copy francs.test_copy from '/home/francs/script/tf/test_copy.txt';
francs=> select * from test_copy;
id | name
----+------
1 | a
2 | b
3 | c
(3 行记录)
备注:导入成功,注意这里用的是 \copy 元子命令,客户端使用 copy 命令会报文件找不到,如下:
2.4 报错1
2francs=# copy francs.test_copy from '/home/francs/script/tf/test_copy.txt';
ERROR: could not open file "/home/francs/script/tf/test_copy.txt" for reading: No such file or directory
备注:由于 copy 命令会到服务端找文件,所以找不到。
2.5 测试导出文件1
2
3
4
5
6
7francs=> copy francs.test_copy to '/home/francs/script/tf/test_copy2.txt';
ERROR: must be superuser to COPY to or from a file
提示: Anyone can COPY to stdout or from stdin. psql s \copy command also works for anyone.
francs=> \copy francs.test_copy to '/home/francs/script/tf/test_copy2.txt';
francs-> \! ls
lib_bak test_copy2.txt test_copy.txt vpn1.sh
备注: 当需要导出表数据到文件时, copy 命令需要以超级用户执行。而 \copy 元子命令不需要。
总结
由于 copy 命令始终是到数据库服务端找文件,当以文件形式导入导出数据时需以超级用户执行,权限要求很高,适合数据库管理员操作;而 \copy 命令可在客户端执行导入客户端的数据文件,权限要求没那么高,适合开发人员,测试人员使用,因为生产库的权限掌握在 DBA 手中。