pgsql.cc 提供对 postgresql.org 官网内容的中文翻译,由 Pigsty 团队维护。
COPY — 在文件和表之间复制数据
COPYtable[ (column[, ...] ) ] FROM { 'filename' |stdin} [ [ WITH ] [ BINARY ] [ OIDS ] [ DELIMITER [ AS ] 'delimiter' ] [ NULL [ AS ] 'null string' ] ] COPYtable[ (column[, ...] ) ] TO { 'filename' |stdout} [ [ WITH ] [ BINARY ] [ OIDS ] [ DELIMITER [ AS ] 'delimiter' ] [ NULL [ AS ] 'null string' ] ]
table一个现有表的名称(可以带模式限定)。
column要复制的可选列列表。如果没有指定列列表,则会使用所有列。
filename输入或输出文件的绝对 Unix 路径名。
stdin指定输入来自客户端应用程序。
stdout指定输出发送到客户端应用程序。
更改字段格式化的行为,强制所有数据以二进制而不是文本格式存储或读取。在二进制模式下不能指定 DELIMITER 或 NULL。
指定为每一行复制内部对象 id(OID)。
delimiter分隔文件每行(一行数据)中各字段的单个字符。
null string表示 NULL 值的字符串。默认是 “\N”(反斜线-N)。例如你可能更喜欢空字符串。
在 copy in 中,任何匹配此字符串的数据项都会被存储为 NULL 值,所以应确保使用与 copy out 相同的字符串。
COPY复制成功完成。
ERROR: reason复制因错误消息中所述的原因而失败。
COPY在 PostgreSQL表与标准文件系统文件之间 传输数据。COPY TO将表的内容复制 到文件,而COPY FROM 则将数据从文件复制到表中(追加到表中已有的数据之 后)。
如果指定了列列表,COPY将只在指定列与文件之间复制数据。 如果表中存在未列入列列表的列,COPY FROM将为这些列插入默认值。
COPY 带文件名时指示 PostgreSQL 后端直接读取或写入文件。该文件必须可由后端访问,且名称必须从后端的角度指定。当指定 stdin 或 stdout 时,数据通过客户端前端流经后端。
不要把 COPY 与 psql 指令 \copy 混淆。\copy 调用 COPY FROM stdin 或 COPY TO stdout,然后在 psql 客户端可访问的文件中获取/存储数据。因此,使用 \copy 时,文件的可访问性和访问权限取决于客户端而不是后端。
COPY只能用于普通表,不能用于视图。
BINARY 关键字强制所有数据以二进制而不是文本格式存储/读取。它比普通的复制命令略快,但二进制复制文件不能跨机器体系结构移植。
默认情况下,文本复制使用制表符("\t")作为字段之间的分隔符。可以用关键字 DELIMITER 把字段分隔符改为任何其他单个字符。数据字段中恰好匹配分隔符的字符将被反斜线引用。
你必须对其值被 COPY TO 读取的任何表拥有 select 权限,并对正被 COPY FROM 插入值的表拥有 insert 权限。对于被 COPY 读取或写入的任何文件,后端还需要适当的 Unix 权限。
COPY FROM将调用目标表上的任何触发器 和检查约束。但是它不会调用规则。
COPY 在第一个错误处停止操作。这对 COPY TO 不会导致问题,但在 COPY FROM 中目标关系已经接收了较早的行。这些行不可见也不可访问,但它们仍占用磁盘空间。如果失败发生在大型复制操作的后期,这可能造成相当大的磁盘空间浪费。你可能希望调用 VACUUM 来回收浪费的空间。
COPY 命令中命名的文件由后端而不是客户端应用直接读取或写入。因此,它们必须位于数据库服务器机器上或可由其访问,而不是客户端上。它们必须可由 PostgreSQL 用户(服务器运行时使用的用户 ID)访问并可读或可写,而不是由客户端。带文件名的 COPY 只允许数据库超级用户使用,因为它允许读取或写入后端有权访问的任何文件。
psql 指令 \copy 以客户端的权限读写客户端机器上的文件,所以它不限于超级用户。
建议 COPY 中使用的文件名总是指定为绝对路径。在 COPY TO 的情况下这是由后端强制的,但对 COPY FROM 你确实可以选择从相对路径指定的文件读取。该路径将相对于后端的工作目录($PGDATA 之下的某处)而不是客户端的工作目录解释。
当 COPY 不带 BINARY 选项使用时,读取或写入的文件是一个文本文件,每个表行占一行。一行中的各列(属性)由分隔字符分隔。属性值本身是由各属性数据类型的输出函数生成(或可被输入函数接受)的字符串。指定的空值字符串用于代替为 NULL 的属性。如果输入文件的任何一行包含多于或少于预期的列数,COPY FROM 将报错。
如果指定了 OIDS,OID 将作为第一列读取或写入,位于用户数据列之前。(如果对没有 OID 的表指定 OIDS 则会报错。)
数据结束可以用只包含反斜线加句点(\.)的单行表示。从 Unix 文件读取时不需要数据结束标记,因为文件结尾已经足够;但在向客户端应用复制数据或从其复制数据时必须提供结束标记。
反斜线字符(\)可用于 COPY 数据中引用否则会被当作行或列分隔符的数据字符。特别是,以下字符如果作为属性值的一部分出现,前面必须有反斜线:反斜线自身、换行符和当前的分隔字符。
COPY FROM识别下列特殊的反斜线序列:
| 序列 | 表示 |
|---|---|
\b |
退格 (ASCII 8) |
\f |
换页 (ASCII 12) |
\n |
新行 (ASCII 10) |
\r |
回车 (ASCII 13) |
\t |
制表 (ASCII 9) |
\v |
纵向制表 (ASCII 11) |
\digits |
反斜线后跟一到三个八进制数字表示该数字代码对应的字节 |
目前,COPY TO从不会输出八进制数字反斜线 序列,但对这些控制字符确实会使用上表列出的其他序列。
绝不要在数据字符 N 或句点(.)前面放反斜线。这样的组合会分别被误认为默认的空值字符串或数据结束标记。上表中未提及的任何其他反斜线引用的字符将被当作它自身。
强烈建议生成 COPY 数据的应用程序把数据中的换行符和回车符分别转换为 \n 和 \r 序列。目前(PostgreSQL 7.2 及更早版本)可以不加任何特殊引用地表示数据回车符,用反斜线加换行符表示数据换行符。但在未来的版本中这些表示默认将不被接受。
注意每一行的结尾由 Unix 风格的换行符("\n")标记。目前,如果给 COPY FROM 一个包含 DOS 或 Mac 风格换行符的文件,它不会按期望的方式工作。这预计在未来的版本中改变。
COPY BINARY 使用的文件格式在 PostgreSQL v7.1 中改变了。新格式由文件头、零个或多个元组和文件尾组成。
文件头由 24 字节的固定字段组成,其后 跟着变长的头部扩展区。 固定字段有:
12 字节序列 PGBCOPY\n\377\r\n\0 --- 注意,空字节 是签名的必要组成部分。(签名的设计目的是便于识别 被非 8 位干净传输破坏的 文件。换行翻译过滤器、丢弃的空字节、丢弃的高位或奇偶校验位的改变都会改变这个签名。)
按源字节序的 int32 常量 0x01020304。如果在此处检测到错误的字节序,读取者原则上可以对后续字段进行字节翻转。
表示文件格式重要方面的 int32 位掩码。位从 0(LSB)到 31(MSB)编号——注意此字段按源端序存储,后续所有整数字段也是如此。位 16-31 保留用于表示关键的文件格式问题;如果读取者在此范围内发现意外置位的位,应当中止。位 0-15 保留用于发出向后兼容格式问题的信号;读取者应简单地忽略此范围内任何意外置位的位。目前只定义了一个标志位,其余必须为零:
为 1 表示转储中包含 OID;为 0 表示不包含
文件头其余部分的 int32 字节长度,不包括自身。在初始版本中它为零,第一个元组紧随其后。未来的格式更改可能允许文件头中存在附加数据。读取者应悄悄跳过它不知道如何处理的任何文件头扩展数据。
头部扩展区被设想为包含一系列可自我标识的块。标志域并不用于告诉 读取程序扩展区中包含哪些内容。头部扩展内容的具体设计留待后续版本决定。
这种设计既允许向后兼容的头部新增(增加头部扩展块,或设置低位标志位), 也允许不向后兼容的更改(设置高位标志位来表明这类更改,并在需要时向扩展区 增加支持数据)。
每个元组以一个 int16 的元组字段数开始。(目前表中所有元组都有相同的计数,但将来不一定总是如此。)然后对元组中的每个字段重复:一个 int16 的 typlen 字,后面可能跟随字段数据。typlen 字段这样解释:
字段为 NULL。没有后续数据。
字段是定长数据类型。typlen 字后面恰好跟随 N 字节数据。
字段是 varlena 数据类型。接下来的四个字节是 varlena 头,它包含包括自身在内的总值长度。
保留供将来使用。
对于非 NULL 字段,读取者可以检查 typlen 与目标列的预期 typlen 匹配。这提供了一种简单但非常有用的检查,确保数据符合预期。
字段之间没有对齐填充或任何其他额外数据。还请注意该格式不区分数据类型是按引用传递还是按值传递。这两项规定都是有意为之:它们可能有助于提高文件的可移植性(当然字节序和浮点格式问题仍然可能阻止你跨机器移动二进制文件)。
如果转储中包含 OID,OID 字段紧跟在字段计数字之后。它是一个正常字段,只是不计入字段计数。特别地,它有一个 typlen——这使处理 4 字节与 8 字节 OID 不至于太痛苦,并且如果将来需要的话还允许 OID 显示为 NULL。
文件尾由一个包含 -1 的 int16 字组成。这很容易与元组的字段计数字区分。
如果字段计数字既不是 -1 也不是预期的列数,读取程序应报告错误。 这提供了一项额外检查,以防与数据失去同步。
下面的例子把一个表复制到标准输出,使用竖线(|)作为字段分隔符:
COPY country TO stdout WITH DELIMITER '|';
把数据从一个 Unix 文件复制到 country 表:
COPY country FROM '/usr1/proj/bray/sql/country_data';
下面是一段适合从 stdin 复制到表中的数据示例(所以最后一行有终止序列):
AF AFGHANISTAN AL ALBANIA DZ ALGERIA ZM ZAMBIA ZW ZIMBABWE \.
注意每行上的空白实际上是一个制表符(TAB)。
下面是相同的数据在一台 Linux/i586 机器上以二进制格式输出的样子。数据经过 Unix 工具 od -c 过滤后显示。该表有三个字段;第一个是 char(2),第二个是 text,第三个是 integer。所有行的第三个字段都是空值。
0000000 P G B C O P Y \n 377 \r \n \0 004 003 002 001 0000020 \0 \0 \0 \0 \0 \0 \0 \0 003 \0 377 377 006 \0 \0 \0 0000040 A F 377 377 017 \0 \0 \0 A F G H A N I S 0000060 T A N \0 \0 003 \0 377 377 006 \0 \0 \0 A L 377 0000100 377 \v \0 \0 \0 A L B A N I A \0 \0 003 \0 0000120 377 377 006 \0 \0 \0 D Z 377 377 \v \0 \0 \0 A L 0000140 G E R I A \0 \0 003 \0 377 377 006 \0 \0 \0 Z 0000160 M 377 377 \n \0 \0 \0 Z A M B I A \0 \0 003 0000200 \0 377 377 006 \0 \0 \0 Z W 377 377 \f \0 \0 \0 Z 0000220 I M B A B W E \0 \0 377 377
SQL92 中没有 COPY 语句。
以下语法由 7.3 之前的应用使用,现在仍受支持:
COPY [ BINARY ] table [ WITH OIDS ]
FROM { 'filename' | stdin }
[ [USING] DELIMITERS 'delimiter' ]
[ WITH NULL AS 'null string' ]
COPY [ BINARY ] table [ WITH OIDS ]
TO { 'filename' | stdout }
[ [USING] DELIMITERS 'delimiter' ]
[ WITH NULL AS 'null string' ]
译文有误、术语不当或页面显示问题,请到译文仓库 pgsty/pgdoc 报告译文问题。 英文原文本身的问题,请在当前版本的对应页面向上游反馈;上游不再修订已结束维护的版本。