pgsql.cc 提供对 postgresql.org 官网内容的中文翻译,由 Pigsty 团队维护。
COPY — 在文件和表之间复制数据
COPYtablename[ (column[, ...] ) ] FROM { 'filename' | STDIN } [ [ WITH ] [ BINARY ] [ OIDS ] [ DELIMITER [ AS ] 'delimiter' ] [ NULL [ AS ] 'null string' ] ] COPYtablename[ (column[, ...] ) ] TO { 'filename' | STDOUT } [ [ WITH ] [ BINARY ] [ OIDS ] [ DELIMITER [ AS ] 'delimiter' ] [ NULL [ AS ] 'null string' ] ]
COPY在 PostgreSQL表与标准文件系统文件之间 传输数据。COPY TO将表的内容复制 到文件,而COPY FROM 则将数据从文件复制到表中(追加到表中已有的数据之 后)。
如果指定了列列表,COPY将只在指定列与文件之间复制数据。 如果表中存在未列入列列表的列,COPY FROM将为这些列插入默认值。
带文件名的 COPY 会指示 PostgreSQL 服务器直接从文件读取或向文件写入。该文件必须可由服务器访问,并且其名称必须从服务器的视角指定。当指定 STDIN 或 STDOUT 时,数据通过客户端与服务器之间的连接传输。
tablename一个现有表的名称(可以是模式限定的)。
column要复制的可选列列表。如果没有指定列列表,则会使用所有列。
filename输入或输出文件的绝对路径名。
STDIN指定输入来自客户端应用程序。
STDOUT指定输出发送到客户端应用程序。
BINARY使所有数据以二进制而不是文本格式存储或读取。在二进制模式下不能指定 DELIMITER 或 NULL 选项。
OIDS指定复制每一行的 OID。(如果为没有 OID 的表指定了 OIDS,就会报错。)
delimiter分隔文件每行(一行数据)中各列的单个字符。默认是制表符。
null string表示空值的字符串。默认是 \N(反斜线-N)。例如你可能更喜欢空字符串。
在 COPY FROM 中,任何匹配此字符串的数据项都会被存储为空值,所以应确保使用与 COPY TO 相同的字符串。
COPY只能用于普通表,不能用于视图。
BINARY关键字使所有数据以二进制格式而不是文本格式 存储/读取。它比普通文本模式略快,但二进制格式的文件在跨机器体系结构 和PostgreSQL版本之间的可移植性较差。
你必须对COPY TO读取其值的表具有 SELECT权限,并对COPY FROM 插入其值的表具有INSERT权限。
COPY 命令中命名的文件由服务器直接读取或写入,而不是由客户端应用进行。因此,这些文件必须位于数据库服务器机器上或可由其访问,而不是客户端上。它们必须可由 PostgreSQL 用户(服务器运行时使用的用户 ID)访问并可读或可写,而不是由客户端访问。带有文件名的 COPY 只允许数据库超级用户使用,因为它允许读取或写入服务器有权访问的任何文件。
不要把 COPY 与 psql 的指令 \copy 混淆。\copy 会调用 COPY FROM STDIN 或 COPY TO STDOUT,然后在 psql 客户端可访问的文件中获取/存储数据。因此,使用 \copy 时,文件的可访问性和访问权限取决于客户端而不是服务器。
建议在COPY中使用的文件名始终指定为绝对路径。 对于COPY TO,服务器会强制这一点;但对于 COPY FROM,你仍可选择从使用相对路径指定的文件中读取。 该路径将相对于服务器进程的工作目录(位于数据目录下某处)而非客户端的工作目录进行解释。
COPY FROM将调用目标表上的任何触发器 和检查约束。但是它不会调用规则。
COPY 会在遇到第一个错误时停止操作。对于 COPY TO,这应当不会导致问题;但对于 COPY FROM,目标表此时已经接收了前面的行。这些行不可见也不可访问,但仍占用磁盘空间。如果在一次大型复制操作已经进行很久后才失败,可能会浪费大量磁盘空间。可以调用 VACUUM 回收这些浪费的空间。
当 COPY 不带 BINARY 选项使用时,读取或写入的数据是一个文本文件,每个表行占一行。一行中的各列由分隔字符分隔。列值本身是由各属性数据类型的输出函数生成(或可被输入函数接受)的字符串。指定的空字符串用于代替为空的列。如果输入文件的任何一行包含多于或少于预期的列数,COPY FROM 将报错。如果指定了 OIDS,OID 将作为第一列读取或写入,位于用户数据列之前。
数据结束可以表示为只包含反斜线加点号(\.)的一行。从文件读取时,不需要数据结束标记,因为文件结束已足够;只有在使用 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 |
反斜线后跟一到三个八进制数字表示该数字代码对应的字节 |
目前,COPY TO从不会输出八进制数字反斜线 序列,但对这些控制字符确实会使用上表列出的其他序列。
任何上表中未提到的其他反斜线字符都将表示其自身。不过,要注意不要 不必要地添加反斜线,因为那可能意外地产生与数据结束标记 (\.)或空值串(默认是\N)匹配的字符串。 这些字符串会在进行任何其他反斜线处理之前先被识别出来。
强烈建议生成 COPY 数据的应用程序把数据中的换行符和回车符分别转换为 \n 和 \r 序列。目前可以用反斜线加回车符表示数据回车符,用反斜线加换行符表示数据换行符。但这些表示在未来的版本中可能不被接受。如果 COPY 文件在不同机器之间传输(例如从 Unix 到 Windows 或反之),它们也非常容易损坏。
COPY TO 将以 Unix 风格的换行符(“\n”)结束每一行。运行在 MS Windows 上的服务器则输出回车符/换行符(“\r\n”),但仅当 COPY 到服务器文件时;为了跨平台一致性,无论服务器平台如何,COPY TO STDOUT 总是发送 “\n”。COPY FROM 可以处理以换行符、回车符或回车符/换行符结尾的行。为了降低本应作为数据的未反斜线转义的换行符或回车符导致错误的风险,如果输入中的行结尾不全部相同,COPY FROM 将提出警告。
COPY BINARY所使用的文件格式在 PostgreSQL 7.4 中发生了变化。新格式由一个 文件头、零个或多个包含行数据的元组以及一个文件尾组成。 头部和数据现在都采用网络字节序。
文件头由 15 字节的固定字段组成,其后 跟着变长的头部扩展区。 固定字段有:
11 字节序列 PGCOPY\n\377\r\n\0 --- 注意,零字节 是签名的必要组成部分。(签名的设计目的是便于识别 被非 8 位干净传输破坏的 文件。行尾翻译过滤器、丢弃的零字节、丢弃的高位或奇偶校验位的改变都会改变这个签名。)
这是一个 32 位整数位掩码,用于表示文件格式的重要属性。位编号从 0(LSB)到 31(MSB)。注意,此字段与文件格式中的所有整数字段一样,采用网络字节序存储(最高有效字节在前)。位 16-31 保留用于表示文件格式的关键问题;如果读取程序发现这个范围内有非预期的位被置位,就应中止。位 0-15 保留用于表示向后兼容的格式问题;读取程序应直接忽略这个范围内非预期的置位。目前仅定义了一个标志位,其余位必须为零:
如果为 1,则数据中包含 OID;如果为 0,则不包含。
32 位整数,表示头部剩余部分的长度(以字节计),不包括该字段本身。 当前该值为零,因此其后紧接着第一个元组。未来对这种格式的更改 可能允许在头部中包含额外数据。如果读取程序不知道如何处理头部 扩展区数据,应静默跳过它。
头部扩展区被设想为包含一系列可自我标识的块。标志域并不用于告诉 读取程序扩展区中包含哪些内容。头部扩展内容的具体设计留待后续版本决定。
这种设计既允许向后兼容的头部新增(增加头部扩展块,或设置低位标志位), 也允许不向后兼容的更改(设置高位标志位来表明这类更改,并在需要时向扩展区 增加支持数据)。
每个元组都以一个 16 位整数计数开头,用于表示该元组中的字段数。(目前, 一个表中的所有元组都应有相同的计数,但这未必永远如此。)随后,对元组中的 每个字段,都会有一个 32 位长度字,后跟该字段数据的相应字节数。(长度字不 包括其本身,且可以为零。)特殊情况下,-1 表示一个 NULL 字段值;在 NULL 情况下,后面不会跟随任何值字节。
字段之间没有对齐填充或任何其他额外数据。
当前,COPY BINARY文件中的所有数据值都假定为 二进制格式(格式代码一)。 可以预见,未来的扩展可能会增加一个允许为各列分别指定格式代码的头部字段。
要确定实际元组数据应采用的二进制格式,你应该参考 PostgreSQL源码,特别是各列 数据类型对应的*send和*recv函数(这些函数通常可 以在源码分发包的src/backend/utils/adt/目录中找到)。
如果文件中包含 OID,OID 字段紧跟在字段计数字之后。它是一个正常字段,只是不计入字段计数。特别地,它有一个长度字——这使处理 4 字节与 8 字节 OID 不至于太痛苦,并且如果将来需要的话还允许 OID 显示为空。
文件尾由一个值为 -1 的 16 位整数构成。这很容易与元组的字段计数字区分开来。
如果字段计数字既不是 -1 也不是预期的列数,读取程序应报告错误。 这提供了一项额外检查,以防与数据失去同步。
下面的示例使用竖线(|)作为字段分隔符将一个表复制到客户端:
COPY country TO STDOUT WITH DELIMITER '|';
要将文件中的数据复制到country表中:
COPY country FROM '/usr1/proj/bray/sql/country_data';
下面给出适合从STDIN复制到表中的示例数据:
AF AFGHANISTAN AL ALBANIA DZ ALGERIA ZM ZAMBIA ZW ZIMBABWE
注意每一行中的空白实际上是一个制表符。
下面是用二进制格式输出的相同数据。该数据是用 Unix 工具 od -c过滤后显示的。该表具有三列, 第一列类型是char(2),第二列类型是text, 第三列类型是integer。所有行在第三列都是空值。
0000000 P G C O P Y \n 377 \r \n \0 \0 \0 \0 \0 \0 0000020 \0 \0 \0 \0 003 \0 \0 \0 002 A F \0 \0 \0 013 A 0000040 F G H A N I S T A N 377 377 377 377 \0 003 0000060 \0 \0 \0 002 A L \0 \0 \0 007 A L B A N I 0000100 A 377 377 377 377 \0 003 \0 \0 \0 002 D Z \0 \0 \0 0000120 007 A L G E R I A 377 377 377 377 \0 003 \0 \0 0000140 \0 002 Z M \0 \0 \0 006 Z A M B I A 377 377 0000160 377 377 \0 003 \0 \0 \0 002 Z W \0 \0 \0 \b Z I 0000200 M B A B W E 377 377 377 377 377 377
SQL 标准中没有COPY语句。
以下语法在 PostgreSQL 7.3 版之前使用,现在仍受支持:
COPY [ BINARY ]tablename[ WITH OIDS ] FROM { 'filename' | STDIN } [ [USING] DELIMITERS 'delimiter' ] [ WITH NULL AS 'null string' ] COPY [ BINARY ]tablename[ WITH OIDS ] TO { 'filename' | STDOUT } [ [USING] DELIMITERS 'delimiter' ] [ WITH NULL AS 'null string' ]
译文有误、术语不当或页面显示问题,请到译文仓库 pgsty/pgdoc 报告译文问题。 英文原文本身的问题,请在当前版本的对应页面向上游反馈;上游不再修订已结束维护的版本。