↑↓ 选择 ↵ 打开 ⌫ 改范围 完整检索页

pgsql.cc 提供对 postgresql.org 官网内容的中文翻译,由 Pigsty 团队维护。

受支持版本: 当前版本 (18) / 17 / 16 / 15 / 14
测试与开发版本: 19 / devel
不受支持的版本: 13 / 12 / 11 / 10 / 9.6 / 9.5 / 9.4 / 9.3 / 9.2 / 9.1 / 9.0 / 8.4 / 8.3 / 8.2 / 8.1 / 8.0 / 7.4 / 7.3 / 7.2 / 7.1 / 7.0 / 6.5 / 6.4
历史版本PostgreSQL 7.1 已于 2006 年 4 月结束社区维护,本页译文保留供仍在使用旧版本的读者参考。新系统请看当前版本。

COPY

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' ]
  

输入

BINARY

更改字段格式化的行为,强制所有数据以二进制而不是文本格式存储或读取。 DELIMITERS 和 WITH NULL 选项与二进制格式无关。

table

一个现有表的名称。

WITH OIDS

指定为每一行复制内部唯一对象 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 保留用于发出向后兼容格式问题的信号;读取者应简单地忽略此范围内任何意外置位的位。目前只定义了一个标志位,其余必须为零:

Bit 16

为 1 表示转储中包含 OID;为 0 表示不包含

头部扩展区长度

文件头其余部分的 int32 字节长度,不包括自身。在初始版本中它为零,第一个元组紧随其后。未来的格式更改可能允许文件头中存在附加数据。读取者应悄悄跳过它不知道如何处理的任何文件头扩展数据。

头部扩展区被设想为包含一系列可自我标识的块。标志域并不用于告诉 读取程序扩展区中包含哪些内容。头部扩展内容的具体设计留待后续版本决定。

这种设计既允许向后兼容的头部新增(增加头部扩展块,或设置低位标志位), 也允许不向后兼容的更改(设置高位标志位来表明这类更改,并在需要时向扩展区 增加支持数据)。

元组

每个元组以一个 int16 的元组字段数开始。(目前表中所有元组都有相同的计数,但将来不一定总是如此。)然后对元组中的每个字段重复:一个 int16 的 typlen 字,后面可能跟随字段数据。typlen 字段这样解释:

Zero

字段为 NULL。没有后续数据。

> 0

字段是定长数据类型。typlen 字后面恰好跟随 N 字节数据。

-1

字段是 varlena 数据类型。接下来的四个字节是 varlena 头,它包含包括自身在内的总值长度。

< -1

保留供将来使用。

对于非 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

SQL92 中没有 COPY 语句。

提交更正

译文有误、术语不当或页面显示问题,请到译文仓库 pgsty/pgdoc 报告译文问题。 英文原文本身的问题,请在当前版本的对应页面向上游反馈;上游不再修订已结束维护的版本。