选择 打开 改范围 完整检索页

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
历史版本PostgreSQL 9.1 已于 2016 年 10 月结束社区维护,本页译文保留供仍在使用旧版本的读者参考。新系统请看当前版本

COPY

COPY — copy data between a file and a table

大纲

COPY table_name [ ( column [, ...] ) ]
    FROM { 'filename' | STDIN }
    [ [ WITH ] ( option [, ...] ) ]

COPY { table_name [ ( column [, ...] ) ] | ( query ) }
    TO { 'filename' | STDOUT }
    [ [ WITH ] ( option [, ...] ) ]

where option can be one of:

    FORMAT format_name
    OIDS [ boolean ]
    DELIMITER 'delimiter_character'
    NULL 'null_string'
    HEADER [ boolean ]
    QUOTE 'quote_character'
    ESCAPE 'escape_character'
    FORCE_QUOTE { ( column [, ...] ) | * }
    FORCE_NOT_NULL ( column [, ...] )
    ENCODING 'encoding_name'

描述

COPYPostgreSQL表与标准文件系统文件之间 传输数据。COPY TO将表的内容复制 文件,而COPY FROM 则将数据文件复制到表中(追加到表中已有的数据之 后)。COPY TO也可以复制 SELECT查询的结果。

如果指定了列列表,COPY将只在指定列与文件之间复制数据。 如果表中存在未列入列列表的列,COPY FROM将为这些列插入默认值。

带文件名的 COPY 会指示 PostgreSQL 服务器直接从文件读取或向文件写入。该文件必须可由服务器访问,并且其名称必须从服务器的视角指定。当指定 STDINSTDOUT 时,数据通过客户端与服务器之间的连接传输。

参数

table_name

一个现有表的名称(可以是模式限定的)。

column

要复制的可选列列表。如果没有指定列列表,则会复制该表所有列。

query

其结果将被复制的SELECTVALUES命令。注意,查询外层必须带圆括号。

filename

输入或输出文件的绝对路径名。Windows 用户可能需要使用 E'' 字符串,并把路径名中用到的反斜线都写成双份。

STDIN

指定输入来自客户端应用程序。

STDOUT

指定输出发送到客户端应用程序。

boolean

指定所选选项是否开启。可以写TRUEON1来启用选项,写FALSEOFF0来禁用它。也可以省略boolean值,此时假定为TRUE

FORMAT

选择要读取或写入的数据格式:textcsv(逗号分隔值)或binary。默认为text

OIDS

指定复制每一行的 OID。(如果为没有 OID 的表指定了 OIDS,或者复制的是一个 query,就会报错。)

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格式时才允许这个选项。

ENCODING

指定文件采用encoding_name编码。如果省略此选项, 将使用当前客户端编码。详见下文注解。

输出

成功完成时,COPY命令会返回形如

COPY count

的命令标签。count为复制的行数。

注解

COPY只能用于普通表,不能用于视图。但可以写 COPY (SELECT * FROM viewname) TO ...

COPY只处理指定的表本身;它不会从子表复制数据 或向子表复制数据。因此,例如COPY table TO显示的数据与 SELECT * FROM ONLY table相同。但COPY (SELECT * FROM table) TO ...可用于导出 继承层次结构中的所有数据。

你必须对COPY TO读取其值的表具有 SELECT权限,并对COPY FROM 插入其值的表具有INSERT权限。对于命令中列出的列, 具有列级权限即可。

COPY 命令中命名的文件由服务器直接读取或写入,而不是由客户端应用进行。因此,这些文件必须位于数据库服务器机器上或可由其访问,而不是客户端上。它们必须可由 PostgreSQL 用户(服务器运行时使用的用户 ID)访问并可读或可写,而不是由客户端访问。带有文件名的 COPY 只允许数据库超级用户使用,因为它允许读取或写入服务器有权访问的任何文件。

不要把 COPYpsql 的指令 \copy 混淆。\copy 会调用 COPY FROM STDINCOPY TO STDOUT,然后在 psql 客户端可访问的文件中获取/存储数据。因此,使用 \copy 时,文件的可访问性和访问权限取决于客户端而不是服务器。

建议在COPY中使用的文件名始终指定为绝对路径。 对于COPY TO,服务器会强制这一点;但对于 COPY FROM,你仍可选择从使用相对路径指定的文件中读取。 该路径将相对于服务器进程的工作目录(通常是集簇的数据目录)而非客户端的工作目录进行解释。

COPY FROM将调用目标表上的任何触发器 和检查约束。但是它不会调用规则。

COPY的输入和输出会受 DateStyle影响。为确保数据能移植到其他可能使用非默认 DateStyle设置的PostgreSQL 安装中,使用COPY TO前应将 DateStyle设置为ISO。同样也建议避免在 IntervalStyle设置为sql_standard时转储 数据,因为负的 interval 值可能会被采用不同 IntervalStyle设置的服务器误解。

即使数据会被服务器直接从一个文件读取或者写入一个文件而不通过 客户端,输入数据也会被根据ENCODING选项或者当前 客户端编码解释,并且输出数据会被根据ENCODING或 者当前客户端编码进行编码。

COPY 会在遇到第一个错误时停止操作。对于 COPY TO,这应当不会导致问题;但对于 COPY FROM,目标表此时已经接收了前面的行。这些行不可见也不可访问,但仍占用磁盘空间。如果在一次大型复制操作已经进行很久后才失败,可能会浪费大量磁盘空间。可以调用 VACUUM 回收这些浪费的空间。

文件格式

文本格式

在使用text格式时,读取或写入的是一个文本文件, 其中表中的每一行对应文件中的一行。每行中的列由分隔符字符隔开。 列值本身是由各属性数据类型的输出函数生成、或可被其输入函数接受的 字符串。对于为空值的列,会使用指定的空值串代替。 如果输入文件中的任何一行包含的列数多于或少于预期, 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 反斜线后跟一到三个八进制数字表示该数字代码对应的字节
\xdigits 反斜线加x后跟一到两个十六进制数字表示该数字代码对应的字节

目前,COPY TO从不会输出八进制或十六进制数字反斜线 序列,但对这些控制字符确实会使用上表列出的其他序列。

任何上表中未提到的其他反斜线字符都将表示其自身。不过,要注意不要 不必要地添加反斜线,因为那可能意外地产生与数据结束标记 (\.)或空值串(默认是\N)匹配的字符串。 这些字符串会在进行任何其他反斜线处理之前先被识别出来。

强烈建议生成COPY数据的应用将数据中的换行和回车分别 转换为\n\r序列。目前,仍然可以用 反斜线加回车表示数据回车,用反斜线加换行表示数据换行。不过, 未来版本可能不再接受这些表示方式。如果COPY文件在不同机器之间 传输(例如从 Unix 到 Windows,或反之),这些表示方式也非常容易被破坏。

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来强制加引号。

CSV格式没有标准方式区分NULL值和空字符串。 PostgreSQLCOPY通过引号来处理 这一区别。NULL会按照NULL参数字符串输出, 且不会被加引号;而与NULL参数字符串匹配的非NULL 值会被加引号。例如,在默认设置下,NULL会写成一个未加引号的 空字符串,而空字符串数据值会写成双引号包围的形式("")。 读取值时遵循类似规则。你可以使用FORCE_NOT_NULL来阻止 对指定列进行NULL输入比较。

因为反斜线在 CSV 格式中不是特殊字符,数据结束标记 \. 也可能作为数据值出现。为避免误解,当 \. 数据值作为一行中的唯一字段出现时,输出时会自动给它加上引号;输入时,如果它带有引号,就不会被解释为数据结束标记。如果正在装载由其他应用程序创建的文件,其中只有一个不带引号的列,而且该列可能包含值 \.,那么可能需要在输入文件中给该值加上引号。

注意

CSV格式中,所有字符都有意义。被空白字符或 DELIMITER之外其他字符包围的带引号值,会把这些字符 也包含进值中。如果你导入的数据来自某个会用空白把CSV 行填充到固定宽度的系统,这可能导致错误。出现这种情况时, 你可能需要在将数据导入PostgreSQL之前, 先预处理CSV文件以移除尾随空白。

注意

CSV 格式既能识别也能生成这样的 CSV 文件:其中带引号的值包含内嵌的回车和换行。因此,这类文件不像文本格式文件那样严格地一行对应表中的一行。

注意

很多程序会生成奇怪、甚至近乎反常的CSV文件,因此这种文件格式更像一种约定而非标准。 因而你可能会遇到无法用这种机制导入的文件,而COPY也可能生成其他程序无法处理的文件。

二进制格式

binary格式选项会使所有数据以二进制格式而不是文本格式 存储或读取。它比文本和CSV格式稍快一些,但二进制格式文件在不同的 机器架构和PostgreSQL版本之间的可移植性较差。 此外,二进制格式与数据类型高度相关。例如,不能从 smallint列输出二进制数据再读入到integer列中, 尽管这种做法在文本格式下是可行的。

binary文件格式由文件头、零个或多个包含 行数据的元组以及一个文件尾构成。头部和数据都以网络字节序表示。

注意

7.4 之前的PostgreSQL版本 使用一种不同的二进制文件格式。

文件头

文件头由 15 字节的固定字段组成,后面跟着一个可变长度的头部扩展区域。固定字段如下:

签名

11 字节序列PGCOPY\n\377\r\n\0 — 注意, 零字节是签名中必不可少的一部分。(该签名的设计目的是便于识别那些在 不具备 8 位透明性的传输过程中遭到破坏的文件。行尾转换过滤器、 零字节丢失、高位丢失或奇偶校验变化等情况都会改变该签名。)

标志域

这是一个 32 位整数位掩码,用于表示文件格式的重要属性。位编号从 0(LSB)到 31(MSB)。注意,此字段与文件格式中的所有整数字段一样,采用网络字节序存储(最高有效字节在前)。位 16-31 保留用于表示文件格式的关键问题;如果读取程序发现这个范围内有非预期的位被置位,就应中止。位 0-15 保留用于表示向后兼容的格式问题;读取程序应直接忽略这个范围内非预期的置位。目前仅定义了一个标志位,其余位必须为零:

位 16

如果为 1,则数据中包含 OID;如果为 0,则不包含。

头部扩展区长度

32 位整数,表示头部剩余部分的长度(以字节计),不包括该字段本身。 当前该值为零,因此其后紧接着第一个元组。未来对这种格式的更改 可能允许在头部中包含额外数据。如果读取程序不知道如何处理头部 扩展区数据,应静默跳过它。

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

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

元组

每个元组都以一个 16 位整数计数开头,用于表示该元组中的字段数。(目前, 一个表中的所有元组都应有相同的计数,但这未必永远如此。)随后,对元组中的 每个字段,都会有一个 32 位长度字,后跟该字段数据的相应字节数。(长度字不 包括其本身,且可以为零。)特殊情况下,-1 表示一个 NULL 字段值;在 NULL 情况下,后面不会跟随任何值字节。

字段之间没有对齐填充或任何其他额外数据。

当前,二进制格式文件中的所有数据值都假定为二进制格式(格式代码一)。 可以预见,未来的扩展可能会增加一个允许为各列分别指定格式代码的头部字段。

要确定实际元组数据应采用的二进制格式,你应该参考 PostgreSQL源码,特别是各列 数据类型对应的*send*recv函数(这些函数通常可 以在源码分发包的src/backend/utils/adt/目录中找到)。

如果文件中包含 OID,则 OID 字段紧跟在字段计数值之后。它是一个普通字段,只是不计入字段数。特别是,它带有一个长度字段 — 这样就能较容易地处理 4 字节或 8 字节的 OID,也允许在将来确有需要时把 OID 表示为空值。

文件尾

文件尾由一个值为 -1 的 16 位整数构成。这很容易与元组的字段计数字区分开来。

如果字段计数字既不是 -1 也不是预期的列数,读取程序应报告错误。 这提供了一项额外检查,以防与数据失去同步。

示例

下面的示例使用竖线(|)作为字段分隔符将一个表复制到客户端:

COPY country TO STDOUT (DELIMITER '|');

要将文件中的数据复制到country表中:

COPY country FROM '/usr1/proj/bray/sql/country_data';

只把名称以 'A' 开头的国家复制到一个文件中:

COPY (SELECT * FROM country WHERE country_name LIKE 'A%') TO '/usr1/proj/bray/sql/a_list_countries.copy';

下面给出适合从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语句。

以下语法曾在PostgreSQL9.0 之前的版本中使用,目前仍受支持:

COPY table_name [ ( column_name [, ...] ) ]
    FROM { 'filename' | STDIN }
    [ [ WITH ]
          [ BINARY ]
          [ OIDS ]
          [ DELIMITER [ AS ] 'delimiter_character' ]
          [ NULL [ AS ] 'null string' ]
          [ CSV [ HEADER ]
                [ QUOTE [ AS ] 'quote_character' ]
                [ ESCAPE [ AS ] 'escape_character' ]
                [ FORCE NOT NULL column_name [, ...] ] ] ]

COPY { table_name [ ( column_name [, ...] ) ] | ( query ) }
    TO { 'filename' | STDOUT }
    [ [ WITH ]
          [ BINARY ]
          [ OIDS ]
          [ DELIMITER [ AS ] 'delimiter_character' ]
          [ NULL [ AS ] 'null string' ]
          [ CSV [ HEADER ]
                [ QUOTE [ AS ] 'quote_character' ]
                [ ESCAPE [ AS ] 'escape_character' ]
                [ FORCE QUOTE { column_name [, ...] | * } ] ] ]

注意,在这种语法中,BINARYCSV被当作独立的关键字,而不是FORMAT选项的参数。

以下语法曾在PostgreSQL7.3 之前的版本中使用,目前仍受支持:

COPY [ BINARY ] table_name [ WITH OIDS ]
    FROM { 'filename' | STDIN }
    [ [USING] DELIMITERS 'delimiter_character' ]
    [ WITH NULL AS 'null_string' ]

COPY [ BINARY ] table_name [ WITH OIDS ]
    TO { 'filename' | STDOUT }
    [ [USING] DELIMITERS 'delimiter_character' ]
    [ WITH NULL AS 'null_string' ]

提交更正

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