pgsql.cc 提供对 postgresql.org 官网内容的中文翻译,由 Pigsty 团队维护。
COPY — 在文件和表之间复制数据
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' ]
更改字段格式化的行为,强制所有数据以二进制而不是文本格式存储或读取。 DELIMITERS 和 WITH NULL 选项与二进制格式无关。
table一个现有表的名称。
指定为每一行复制内部唯一对象 id(OID)。
filename输入或输出文件的绝对 Unix 路径名。
stdin指定输入来自客户端应用程序。
stdout指定输出发送到客户端应用程序。
delimiter分隔文件每行(一行数据)中各字段的字符。
null string表示 NULL 值的字符串。默认是 “\N”(反斜线-N)。例如你可能更喜欢空字符串。
在 copy in 中,任何匹配此字符串的数据项都会被存储为 NULL 值,所以应确保使用与 copy out 相同的字符串。
COPY复制成功完成。
ERROR: reason复制因错误消息中所述的原因而失败。
COPY 在 Postgres 表和标准文件系统文件之间移动数据。 COPY TO 把一个表的全部内容复制到文件,而 COPY FROM 把数据从文件复制到表(把数据追加到表中已有内容之后)。
COPY 指示 Postgres 后端直接读取或写入文件。如果指定了文件名,该文件必须可由后端访问,且名称必须从后端的角度指定。 如果指定了 stdin 或 stdout,数据通过客户端前端流经后端。
不要把 COPY 与 psql 指令 \copy 混淆。 \copy 调用 COPY FROM stdin 或 COPY TO stdout,然后在 psql 客户端可访问的文件中获取/存储数据。因此,使用 \copy 时,文件的可访问性和访问权限取决于客户端而不是后端。
BINARY 关键字强制所有数据以二进制而不是文本格式存储/读取。它比普通的复制命令略快,但二进制复制文件不能跨机器体系结构移植。
默认情况下,文本复制使用制表符("\t")作为字段之间的分隔符。可以用关键字短语 USING DELIMITERS 把字段分隔符改为任何其他单个字符。数据字段中恰好匹配分隔符的字符将被反斜线引用。注意分隔符总是单个字符。如果在分隔符字符串中指定了多个字符,只使用第一个字符。
你必须对其值被 COPY 读取的任何表拥有 select 访问权限,并对正被 COPY 插入值的表拥有 insert 或 update 访问权限。对于被 COPY 读取或写入的任何文件,后端还需要适当的 Unix 权限。
COPY TO 既不调用规则也不作用于列默认值。它确实会调用触发器和检查约束。
COPY 在第一个错误处停止操作。这对 COPY FROM 不会导致问题,但在 COPY TO 中目标关系已经接收了较早的行。这些行不可见也不可访问,但它们仍占用磁盘空间。如果失败发生在大型复制操作的后期,这可能造成相当大的磁盘空间浪费。你可能希望调用 VACUUM 来回收浪费的空间。
COPY 命令中命名的文件由后端而不是客户端应用直接读取或写入。因此,它们必须位于数据库服务器机器上或可由其访问,而不是客户端上。它们必须可由 Postgres 用户(后端运行时使用的用户 ID)访问并可读或可写,而不是由客户端。带文件名的 COPY 只允许数据库超级用户使用,因为它允许写入后端有权写入的任何文件。
psql 指令 \copy 以客户端的权限读写客户端机器上的文件,所以它不限于超级用户。
建议 COPY 中使用的文件名总是指定为绝对路径。在 COPY TO 的情况下这是由后端强制的,但对 COPY FROM 你确实可以选择从相对路径指定的文件读取。该路径将相对于后端的工作目录($PGDATA 之下的某处)而不是客户端的工作目录解释。
当 COPY TO 不带 BINARY 选项使用时,生成的文件中每一行(实例)占一行,各列(属性)由分隔字符分隔。嵌入的分隔字符前面会有一个反斜线字符("\")。属性值本身是由与各属性类型关联的输出函数生成的字符串。类型的输出函数不应尝试生成反斜线字符;这将由 COPY 自身处理。
每个实例的实际格式是
<attr1><separator><attr2><separator>...<separator><attrn><newline>
注意每一行的结尾由 Unix 风格的换行符("\n")标记。如果给 COPY FROM 一个包含 DOS 或 Mac 风格换行符的文件,它不会按期望的方式工作。
如果指定了 WITH OIDS,OID 将作为第一列输出。
如果 COPY TO 把输出发送到标准输出而不是文件,在最后一行之后它将发送一个反斜线("\")和一个句点(".")后跟一个换行符。类似地,如果 COPY FROM 从标准输入读取,它将期待一个反斜线("\")和一个句点(".")后跟一个换行符,作为一行上表示文件结束的前三个字符。不过,如果在找到这个特殊的文件结束模式之前输入连接就关闭了,COPY FROM 也会正确终止(随后后端自身也终止)。
反斜线字符还有其他特殊含义。字面反斜线字符表示为两个连续的反斜线("\\")。字面制表符表示为一个反斜线加一个制表符。(如果你使用的列分隔符不是制表符,要把它包含在数据中需对该分隔符加反斜线。)字面换行符表示为一个反斜线加一个换行符。在加载不是由 Postgres 生成的文本数据时,你需要把反斜线字符("\")转换为双反斜线("\\")以确保正确加载。
COPY BINARY 使用的文件格式在 Postgres 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 为可选的话,还允许 OID 显示为 NULL。
文件尾由一个包含 -1 的 int16 字组成。这很容易与元组的字段计数字区分。
如果字段计数字既不是 -1 也不是预期的列数,读取程序应报告错误。 这提供了一项额外检查,以防与数据失去同步。
下面的例子把一个表复制到标准输出,使用竖线(|)作为字段分隔符:
COPY country TO stdout USING DELIMITERS '|';
把数据从一个 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 语句。
译文有误、术语不当或页面显示问题,请到译文仓库 pgsty/pgdoc 报告译文问题。 英文原文本身的问题,请在当前版本的对应页面向上游反馈;上游不再修订已结束维护的版本。