合 PG中的SQL copy和元命令copy命令
Tags: PGPostgreSQL数据迁移导出数据COPY文本文件导入数据
COPY和“\copy”的区别
psql支持文件数据导入到数据库,也支持数据库表数据导出到文件中。 COPY命令和\copy 命令都支持这两类操作,但两者有如下区别:
- COPY 命令是SQL命令,\copy 命令是元命令。
- 执行COPY 命令的用户必须具有SUPERUSER超级权限(将数据通过stdin/stdout方式导入导出情况除外)或授予了默认角色
pg_read_server_files
、pg_write_server_files
及pg_execute_server_program
之一的用户,而 \copy 元命令不需要SUPERUSER权限。 - COPY 命令读取或写入数据库服务端主机上的文件,而 \copy 元命令是从psql客户端主机读取或写入文件。
- 从性能方面看, 大数据量导出文件或大文件数据导入数据库,COPY 比 \copy 性能高。
COPY命令
COPY — 在一个文件和一个表之间复制数据
大纲
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | COPY table_name [ ( column_name [, ...] ) ] FROM { 'filename' | PROGRAM 'command' | STDIN } [ [ WITH ] ( option [, ...] ) ] [ WHERE condition ] COPY { table_name [ ( column_name [, ...] ) ] | ( query ) } TO { 'filename' | PROGRAM 'command' | STDOUT } [ [ WITH ] ( option [, ...] ) ] 其中 option 可以是下列之一: FORMAT format_name 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 [, ...] ) FORCE_NULL ( column_name [, ...] ) ENCODING 'encoding_name' |
描述
COPY
在 PostgreSQL表和标准文件系统文件之间 移动数据。COPY TO
把一个表的内容复制 到一个文件,而COPY FROM
则从一个文件复制数据到一个表(把数据追加到表中原有数 据)。COPY TO
也能复制一个 SELECT
查询的结果。
如果指定了一个列列表,COPY TO
将只把指定列的数据复制到文件。对于COPY FROM
,文件中的每个字段将按顺序插入到指定列中。COPY FROM
命令的列列表中没有指定的表列则会采纳其默认值。
带一个文件名的COPY
指示 PostgreSQL服务器直接从一个文件读取 或者写入到一个文件。该文件必须是 PostgreSQL用户(运行服务器的用户 ID) 可访问的并且应该以服务器的视角来指定其名称。当指定了 PROGRAM
时,服务器执行给定的命令并且从该程序的标准 输出读取或者写入到该程序的标准输入。该程序必须以服务器的视角指定,并且 必须是PostgreSQL用户可执行的。在指定 STDIN
或者STDOUT
时,数据会通过客 户端和服务器之间的连接传输。
参数
table_name
一个现有表的名称(可以是模式限定的)。
column_name
可选的要被复制的列列表。如果没有指定列列表,则该表的所有列除了生成的列都会被复制。
query
其结果要被复制的SELECT、 VALUES、 INSERT、UPDATE或者 DELETE命令。注意查询周围的圆括号是必要的。对于
INSERT
、UPDATE
以及DELETE
查询,必须提供一个 RETURNING 子句并且 目标关系不能具有会扩展成多条语句的条件规则、ALSO
规则或者INSTEAD
规则。filename
输入或者输出文件的路径名。一个输入文件的名称可以是一个绝对或相对路径, 但一个输出文件的名称必须是绝对路径。Windows 用户可能需要使用一个
E''
字符串并且双写路径名称中使用的任何反斜线。PROGRAM
一个要执行的命令。在
COPY FROM
中,输入 将从该命令的标准输出读取,而在COPY TO
中,输出会 写入到该命令的标准输入。注意该命令是由 shell 调用,因此如果你需要传递任何来自不可信来源的 参数给 shell 命令,你必须小心地剥离那些可能对 shell 有特殊意义的特殊 字符。出于安全原因,最好使用一个固定的命令字符串,或者至少避免传递 任何用户输入到其中。STDIN
指定输入来自客户端应用。
STDOUT
指定输出会去到客户端应用。
boolean
指定选中的选项是应该被关闭还是打开。可以写
TRUE
、ON
或1
来启用选项,写FALSE
、OFF
或0
禁用它。boolean
值也可以被省略, 那样会假定为TRUE
。FORMAT
选择要读取或者写入的数据格式:
text
、csv
(逗号分隔值)或者binary
。 默认是text
。FREEZE
请求复制已经完成了行冻结的数据,就好像在运行
VACUUM FREEZE
命令之后复制。这是为了初始 数据载入的性能而设计的。只有被载入表已经在当前子事务中被创建 或截断、该事务中没有游标打开并且该事务没有持有更旧的快照时, 行才会被冻结。目前无法在分区表上执行COPY FREEZE
。注意一旦成功地载入,所有其他会话将能立即看到该数据。这违背了 普通的 MVCC 可见性规则,指定该选项的用户应该注意这可能会导致 的潜在问题。DELIMITER
指定分隔文件每行中各列的字符。文本格式中默认是一个制表符, 而
CSV
格式中默认是一个逗号。这必须是一个单一 的单字节字符。使用binary
格式时不允许这个选项。NULL
指定表示一个空值的字符串。文本格式中默认是
\N
(反斜线-N),CSV
格式中默认 是一个未加引用的空串。在你不想区分空值和空串的情况下,即使在文本 格式中你也可能更喜欢空串。使用binary
格式时不允许这 个选项。注意在使用COPY FROM
时,任何匹配 这个串的数据项将被存储为空值,因此你应该确定你使用的是和COPY TO
时相同的串。HEADER
指定文件包含标题行,其中有每一列的名称。在输出时,第一行包含 来自表的列名。在输入时,第一行会被忽略。只有使用
CSV
格式时才允许这个选项。QUOTE
指定一个数据值被引用时使用的引用字符。默认是双引号。 这必须是一个单一的单字节字符。只有使用
CSV
格式时才允许这个选项。ESCAPE
指定应该出现在一个匹配
QUOTE
值的数据字符之前 的字符。默认和QUOTE
值一样(这样如果引用字符 出现在数据中,它会被双写)。这必须是一个单一的单字节字符。 只有使用CSV
格式时才允许这个选项。FORCE_QUOTE
强制必须对每个指定列中的所有非
NULL
值使用引用。NULL
输出不会被引用。如果指定了*
, 所有列的非NULL
值都将被引用。只有在COPY TO
中使用CSV
格式时才允许 这个选项。FORCE_NOT_NULL
不要把指定列的值与空值串匹配。在空值串就是空串的默认情况下, 这意味着空串将被读作长度为零的字符串而不是空值(即使它们没有 被引用)。只有在
COPY FROM
中使用CSV
格式时才允许这个选项。FORCE_NULL
将指定列的值与空值串匹配(即使它已经被加上引号),并且在找到 匹配时将该值设置为
NULL
。在空值串就是空串的默认 情况下,这会把一个被引用的空串转换为 NULL。 只有在COPY FROM
中使用CSV
格式时才允许这个选项。ENCODING
指定文件被以
encoding_name
编码。如果省略 这个选项,将使用当前的客户端编码。详见下文的注解。WHERE
WHERE
子句是可选的,其一般形式是:WHERE *
condition*
其中condition
是计算结果为boolean
类型的任意表达式。任何不满足此条件的行都不会插入到表中。在用实际的行值替换任何变量引用时,如果该行返回true,则该行满足条件。目前,在WHERE
表达式中不允许使用子查询,并且值的计算不会看到COPY
本身所做的任何更改(当表达式包含对VOLATILE
函数的调用时,这一点很重要)。
输出
在成功完成时,一个COPY
命令会返回一个形为
1 | COPY count |
的命令标签。 count
是被复制 的行数。
注意
如果命令不是COPY ... TO STDOUT
或者等效的 psql元命令\copy ... to stdout
, psql将只打印这个命令标签。这是为了防止弄混 命令标签和刚刚打印的数据。
注解
COPY TO
只能被用于纯粹的表,不能用于视图。 不过你可以写COPY (SELECT * FROM *
viewname*) TO ...
来拷贝一个视图的当前内容。
COPY FROM
可以被用于普通表、外部表、分区表或者具有INSTEAD OF INSERT
触发器的视图。
COPY
只处理提到的表,它不会从子表复制 数据或者复制数据到子表中。例如 COPY *
table* TO
会显示与SELECT * FROM ONLY *
table*
相同的数据。而COPY (SELECT * FROM *
table*) TO ...
可以被用来转储一个继承层次中的所有数据。
你必须拥有被COPY TO
读取的表上的选择特权, 以及被COPY FROM
插入的表上的插入特权。 拥有在命令中列出的列上的特权就足够了。
如果对表启用了行级安全性,相关的SELECT
策略将应用于COPY *
table* TO
语句。当前,有行级安全性的表不支持COPY FROM
。不过可以使用等效的INSERT
语句。
COPY
命令中提到的文件会被服务器(而不是 客户端应用)直接读取或写入。因此它们必须位于数据库服务器(不是客户 端)的机器上或者是数据库服务器可以访问的。它们必须是 PostgreSQL用户(运行服务器的用户 ID)可访问的并且是可读或者可写的。类似地,用PROGRAM
指定的命令也会由服务器(不是客户端应用)直接执行,它也必须是 PostgreSQL用户可以执行的。 只允许数据库超级用户或者授予了默认角色pg_read_server_files
、pg_write_server_files
及pg_execute_server_program
之一的用户COPY
一个文件或者命令, 因为它允许读取或者写入服务器有特权访问的任何文件或者运行服务器有特权访问的程序。
不要把COPY
和 psql指令 \copy
弄混。\copy
会调用 COPY FROM STDIN
或者COPY TO STDOUT
,然后读取/存储一个 psql客户端可访问的文件中的数据。 因此,在使用\copy
时,文件的可访 问性和访问权利取决于客户端而不是服务器。
我们推荐在COPY
中使用的文件名总是 指定为一个绝对路径。在COPY TO
的 情况下服务器会强制这一点,但是对于 COPY FROM
你可以选择从一个用相对 路径指定的文件中读取。该路径将根据服务器进程(而不是客户端) 的工作目录(通常是集簇的数据目录)解释。
用PROGRAM
执行一个命令可能会受到操作系统 的访问控制机制(如 SELinux)的限制。
COPY FROM
将调用目标表上的任何触发器 和检查约束。但是它不会调用规则。
对于标识列,COPY FROM
命令将总是写上输入数据中提供的列值,这和INSERT
的选项OVERRIDING SYSTEM VALUE
的行为一样。
COPY
输入和输出受到 DateStyle
的影响。为了确保到其他 可能使用非默认DateStyle
设置的 PostgreSQL安装的可移植性,在使用 COPY TO
前应该把 DateStyle
设置为ISO
。避免转储把 IntervalStyle
设置为 sql_standard
的数据也是一个好主意,因为负的区间值可能会 被具有不同IntervalStyle
设置的服务器解释错误。
即使数据会被服务器直接从一个文件读取或者写入一个文件而不通过 客户端,输入数据也会被根据ENCODING
选项或者当前 客户端编码解释,并且输出数据会被根据ENCODING
或 者当前客户端编码进行编码。
COPY
会在第一个错误处停止操作。这在 COPY TO
的情况下不会导致问题,但是 在COPY FROM
中目标表将已经收到了一 些行。这些行将不会变得可见或者可访问,但是它们仍然占据磁盘空间。 如果在一次大型的复制操作中出现错误,这可能浪费相当可观的磁盘空间。 你可能希望调用VACUUM
来恢复被浪费的 空间。
FORCE_NULL
和FORCE_NOT_NULL
可以被同时 用在同一列上。这会导致把已被引用的空值串转换为空值并且把未引用的空值 串转换为空串。
文件格式
文本格式
在使用text
格式时,读取或写入的是一个文本文件, 其中每一行就是表中的一行。一行中的列被定界字符分隔。列值 本身是由输出函数产生的或者是可被输入函数接受的属于每个属性 数据类型的字符串。在为空值的列的位置使用指定的空值串。如果 输入文件的任何行包含比预期更多或者更少的列, COPY FROM
将会抛出一个错误。
数据的结束可以表示为一个只包含反斜线-点号(\.
)的 单一行。从一个文件读取时,数据结束标记并不是必要的,因为文件 结束符就已经足够用了。只有使用 3.0 客户端协议之前的客户端应用 复制数据时才需要它。
反斜线字符(\
)可以被用在 COPY
数据中来引用被用作行或者列定界符的 字符。特别地,如果下列字符作为一个列值的一部分出现,它们 必须\被前置一个反斜线:反斜线本身、新行、回车以及 当前的定界符字符。
COPY TO
会不加任何反斜线返回指定的空值串。 相反,COPY FROM
会在移除反斜线之前把输入 与空值串相匹配。因此,一个空值串(例如\N
)不会与实 际的数据值\N
(它会被表示为\\N
)搞混。
COPY FROM
识别下列特殊的反斜线序列:
序列 | 表示 |
---|---|
\b | 退格 (ASCII 8) |
\f | 换页 (ASCII 12) |
\n | 新行 (ASCII 10) |
\r | 回车 (ASCII 13) |
\t | 制表 (ASCII 9) |
\v | 纵向制表 (ASCII 11) |
\ digits | 反斜线后跟一到三个十进制位表示该数字代码对应的字符 |
\x digits | 反斜线加x 后跟一到三个十六进制位表示该数字代码对应的字符 |
当前,COPY TO
不会发出一个十进制或十六进制位 反斜线序列,但是它确实把上面列出的其他序列用于那些控制字符。
任何上述表格中没有提到的其他反斜线字符将被当作表示其本身。不过,要注意 增加不必要的反斜线,因为那可能意外地产生一个匹配数据结束标记( \.
)或者空值串(默认是\N
)的字符串。这些字符串 将在完成任何其他反斜线处理之前被识别。
强烈建议产生COPY
数据的应用把数据新行和回车分别 转换为\n
和\r
序列。当前可以把一个数据回车表示为 一个反斜线和回车,把一个数据新行表示为一个反斜线和新行。不过,未来的发行 可能不会接受这些表示。如果在不同的机器之间(例如从 Unix 到 Windows) 传输COPY
文件,它们也很容易受到破坏。
COPY TO
将用一个 Unix 风格的新行( “\n
”)终止每一行。运行在 Microsoft Windows 上的服务器则会输出回车/新行(“\r\n
”),不过只对 COPY
到一个服务器文件这样做。为了做到跨平台一致, COPY TO STDOUT
总是发送“\n
”而 不管服务器平台是什么。COPY FROM
能够处理以 新行、回车或者回车/新行结尾的行。为了减少由作为数据的未加反斜线的新行 或者回车带来的风险,如果输出中的行结束并不完全相似, COPY FROM
将会抱怨。
CSV 格式
这种格式选项被用于导入和导出很多其他程序(例如电子表格)使用的逗号 分隔值(CSV
)文件格式。不同于 PostgreSQL标准文本格式使用的转义 规则,它产生并且识别一般的 CSV 转义机制。
每个记录中的值用DELIMITER
字符分隔。如果值包含 定界符字符、QUOTE
字符、NULL
字符串、 一个回车或者换行字符,那么整个值会被加上QUOTE
字符 作为前缀或者后缀,并且在该值内QUOTE
字符或者 ESCAPE
字符的任何一次出现之前放上转义字符。在输出 指定列中非NULL
值时,还可以使用 FORCE_QUOTE
来强制加上引用。