Note

COPY

COPY —在文件和表之间复制数据

Synopsis

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

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

where option can be one of:

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

Description

COPY在 PostgreSQL 表和标准文件系统文件之间移动数据。 COPY TO将表的内容复制到文件中,而COPY FROM文件的数据复制到表中(将数据追加到表中已有的内容中)。 COPY TO还可以复制SELECT查询的结果。

如果指定了列列表,则COPY TO仅将指定列中的数据复制到文件中。对于COPY FROM,文件中的每个字段按 Sequences 插入到指定的列中。未在COPY FROM列列表中指定的表列将接收其默认值。

带有文件名的COPY指示 PostgreSQL 服务器直接从文件读取或写入文件。 PostgreSQL 用户必须可以访问该文件(服务器运行时使用的用户 ID),并且必须从服务器的角度指定名称。当指定PROGRAM时,服务器将执行给定命令并从程序的标准输出中读取,或写入程序的标准 Importing。该命令必须从服务器的角度指定,并且可由 PostgreSQL 用户执行。当指定STDINSTDOUT时,数据将通过 Client 端和服务器之间的连接进行传输。

Parameters

对于INSERTUPDATEDELETE查询,必须提供 RETURNING 子句,并且目标关系不得具有条件规则,ALSO规则或扩展为多个语句的INSTEAD规则。

请注意,该命令是由 Shell 程序调用的,因此,如果您需要将来自不受信任来源的任何参数传递给 Shell 程序命令,则必须小心删除或转义可能对 Shell 程序有特殊含义的任何特殊字符。出于安全原因,最好使用固定的命令字符串,或者至少避免在其中传递任何用户 Importing。

请注意,数据成功加载后,所有其他会话将立即能够看到数据。这违反了 MVCC 可见性的常规规则,指定用户应注意这可能引起的潜在问题。

Note

使用COPY FROM时,与该字符串匹配的任何数据项都将存储为空值,因此您应确保使用与COPY TO相同的字符串。

Outputs

成功完成后,COPY命令将返回以下形式的命令标签:

COPY count

Note

仅当命令不是COPY ... TO STDOUT或等效的 psql 元命令\copy ... to stdout时,psql 才会打印此命令标记。这是为了防止将命令标记与刚刚打印的数据混淆。

Notes

COPY TO只能用于普通表,不能用于视图。但是,您可以编写COPY (SELECT * FROM viewname) TO ...来复制视图的当前内容。

COPY FROM可以与普通表,外部表或分区表一起使用,也可以与具有INSTEAD OF INSERT触发器的视图一起使用。

COPY仅处理名为的特定表;它不会在子表之间复制数据。因此,例如COPY table TO显示的数据与SELECT * FROM ONLY table相同。但是COPY (SELECT * FROM table) TO ...可用于转储继承层次结构中的所有数据。

您必须对由COPY TO读取值的表具有选择特权,并且对由COPY FROM插入值的表具有插入特权。对命令中列出的列具有列特权就足够了。

如果为表启用了行级安全性,则相关的SELECT策略将应用于COPY table TO语句。当前,具有行级安全性的表不支持COPY FROM。请使用等效的INSERT语句。

COPY命令中命名的文件由服务器而不是 Client 端应用程序直接读取或写入。因此,它们必须驻留在数据库服务器计算机上,或者必须位于数据库服务器计算机上,而不是 Client 端可以访问。 PostgreSQL 用户(服务器运行时使用的用户 ID),而不是 Client 端,必须是可访问和可读写的。同样,用PROGRAM指定的命令直接由服务器执行,而不是由 Client 端应用程序执行,必须由 PostgreSQL 用户执行。 COPY仅允许数据库超级用户或被授予默认角色pg_read_server_filespg_write_server_filespg_execute_server_program之一的用户命名文件或命令,因为它允许读取或写入任何文件或运行服务器有权访问的程序。

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

建议始终将COPY中使用的文件名指定为绝对路径。对于COPY TO,这是由服务器强制执行的,但是对于COPY FROM,您可以选择从相对路径指定的文件中读取。该路径将相对于服务器进程的工作目录(通常是集群的数据目录)而不是 Client 端的工作目录进行解释。

PROGRAM执行命令可能会受到 os 的访问控制机制(例如 SELinux)的限制。

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

对于标识列,COPY FROM命令将始终写入 Importing 数据中提供的列值,例如INSERT选项OVERRIDING SYSTEM VALUE

COPYImporting 和输出受DateStyle影响。为了确保可移植到其他可能使用非默认DateStyle设置的 PostgreSQL 安装,应在使用COPY TO之前将DateStyle设置为ISO。最好避免将IntervalStyle设置为sql_standard时转储数据,因为对于IntervalStyle具有不同设置的服务器可能会误解负间隔值。

Importing 数据将根据ENCODING选项或当前 Client 端编码进行解释,而输出数据将以ENCODING或当前 Client 端编码进行编码,即使数据没有通过 Client 端,而是由服务器直接从文件中读取或写入文件中。

COPY在第一个错误时停止操作。如果出现COPY TO,这应该不会导致问题,但是目标表将已经收到COPY FROM中的较早行。这些行将不可见或不可访问,但仍会占用磁盘空间。如果故障在大型复制操作中发生得很好,则可能会浪费大量磁盘空间。您可能希望调用VACUUM来恢复浪费的空间。

FORCE_NULLFORCE_NOT_NULL可以在同一列上同时使用。这导致将带引号的空字符串转换为空值,将未带引号的空字符串转换为空字符串。

File Formats

Text Format

使用text格式时,读取或写入的数据是一个文本文件,每表行一行。行中的列由定界符分隔。列值本身是每个属性的数据类型的输出函数生成的字符串,或 Importing 函数可接受的字符串。使用指定的空字符串代替空列。如果 Importing 文件的任何行包含的列比预期的多或少,则COPY FROM将引发错误。如果指定OIDS,则将 OID 读取或写入为用户数据列之前的第一列。

数据结尾可以由仅包含反斜杠句点(\.)的一行表示。从文件读取时,数据末尾标记不是必需的,因为文件末尾可以很好地工作;仅在使用 3.0 之前的 Client 端协议向 Client 端应用程序复制数据或从 Client 端应用程序复制数据时才需要。

可以在COPY数据中使用反斜杠字符(\)来引用否则可能被用作行或列定界符的数据字符。特别是,如果以下字符* *作为列值的一部分出现,则必须在它们前面加上反斜杠:反斜杠本身,换行符,回车符和当前定界符。

指定的空字符串由COPY TO发送,不添加任何反斜杠;相反,在删除反斜杠之前,COPY FROM将 Importing 与空字符串进行匹配。因此,不能将诸如\N之类的空字符串与实际数据值\N(将其表示为\\N)混淆。

COPY FROM可以识别以下特殊的反斜杠序列:

Sequence Represents
\b 退格键(ASCII 8)
\f 换页(ASCII 12)
\n 换行符(ASCII 10)
\r 回车符(ASCII 13)
\t 制表符(ASCII 9)
\v 垂直标签(ASCII 11)
\ digits 反斜杠后跟一到三个八进制数字指定带有该数字代码的字符
\x digits 反斜杠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可以处理以换行符,回车符或回车符/换行符结尾的行。为了减少由于反斜杠换行符或回车符(作为数据而引起的错误)的风险,如果 Importing 中的行尾并不完全相同,则COPY FROM将进行投诉。

CSV Format

此格式选项用于导入和导出许多其他程序(例如电子表格)使用的逗号分隔值(CSV)文件格式。它会生成并识别常见的 CSV 转义机制,而不是 PostgreSQL 的标准文本格式使用转义规则。

每个 Logging 的值用DELIMITER字符分隔。如果该值包含定界符,QUOTE字符,NULL字符串,回车符或换行符,则整个值将以QUOTE字符作为前缀和后缀,并且在QUOTE字符或ESCAPE字符前面有转义字符。在特定列中输出非NULL值时,也可以使用FORCE_QUOTE强制引号。

CSV格式没有标准的方法可以将NULL值与空字符串区分开。 PostgreSQL 的COPY通过引用来处理。 NULL作为NULL参数字符串输出,不加引号,而与NULL参数字符串匹配的非NULL值则加引号。例如,在默认设置下,NULL被写为无引号的空字符串,而空字符串数据值被写成双引号("")。读取值遵循类似的规则。您可以使用FORCE_NOT_NULL来防止NULL对特定列的 Importing 比较。您还可以使用FORCE_NULL将带引号的空字符串数据值转换为NULL

因为反斜杠不是CSV格式的特殊字符,所以\.(数据结束标记)也可以显示为数据值。为避免任何误解,出现在行上作为单独条目的\.数据值会在输出上自动加引号,并且在 Importing(如果加引号)时也不会解释为数据结束标记。如果要加载的文件是由另一个应用程序创建的,该文件只有一个未加引号的列,并且值可能为\.,则可能需要在 Importing 文件中引用该值。

Note

CSV格式的所有字符均有效。用引号引起来的值用空格或DELIMITER以外的任何字符括起来,将包括这些字符。如果您从将CSV行用空白填充到某个固定宽度的系统中导入数据,则可能会导致错误。如果出现这种情况,则可能需要先预处理CSV文件以删除尾随空白,然后再将数据导入 PostgreSQL。

Note

CSV 格式将识别并生成带有引用值的 CSV 文件,这些值包含嵌入式回车符和换行符。因此,与文本格式的文件相比,文件并非严格限于每行一行。

Note

许多程序会生成奇怪的,有时是错误的 CSV 文件,因此文件格式更像是一种约定,而不是一种标准。因此,您可能会遇到一些无法使用此机制导入的文件,并且COPY可能会生成其他程序无法处理的文件。

Binary Format

binary格式选项使所有数据以二进制格式而不是文本形式存储/读取。它比文本和CSV格式要快一些,但是二进制格式的文件在计算机体系结构和 PostgreSQL 版本之间的可移植性较差。同样,二进制格式是非常特定于数据类型的。例如,从smallint列输出二进制数据并将其读入integer列将不起作用,即使这样在文本格式下也可以正常工作。

binary文件格式由文件头,包含行数据的零个或多个 Tuples 和文件尾部组成。Headers 和数据按网络字节 Sequences 排列。

Note

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

File Header

文件头由 15 个字节的固定字段组成,后跟可变长度的头扩展区。固定字段是:

头扩展区被设想为包含一系列自识别块。标志字段不是要告诉 Reader 扩展区域中的内容。Headers 扩展内容的特定设计留给以后的版本。

这种设计既允许向后兼容的 Headers 添加(添加 Headers 扩展块,或设置低位标志位),也允许非向后兼容的更改(设置高位标志位来发出此类更改 signal,并向 extensions 添加支持数据)区域(如果需要)。

Tuples

每个 Tuples 都以 Tuples 中字段数的 16 位整数开始。 (当前,表中的所有 Tuples 都将具有相同的计数,但这可能并不总是正确的.)然后,对于 Tuples 中的每个字段重复此操作,将有一个 32 位长的字,后跟那么多字节的字段数据。 (长度字不包括自身,并且可以为零.)在特殊情况下,-1 表示 NULL 字段值。在 NULL 情况下,没有值字节。

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

当前,二进制格式文件中的所有数据值都假定为二进制格式(格式代码 1)。可以预期,将来的扩展可能会添加一个 Headers 字段,以允许指定每个列的格式代码。

要为实际的 Tuples 数据确定适当的二进制格式,应查阅 PostgreSQL 源,特别是每列数据类型的*send*recv函数(通常这些函数在源分发的src/backend/utils/adt/目录中找到)。

如果文件中包含 OID,则 OID 字段紧跟在字段计数字之后。这是一个普通字段,但不包括在字段计数中。特别是它有一个长度字-这将允许处理 4 字节和 8 字节的 OID,而不会带来太多麻烦,并且如果确实需要的话,也可以将 OID 显示为 null。

File Trailer

文件尾部由一个包含-1 的 16 位整数字组成。这很容易与 Tuples 的字段计数字区分开。

如果字段计数字既不是-1 也不是预期的列数,则 Reader 应报告错误。这提供了额外的检查,以防止以某种方式与数据不同步。

Examples

下面的示例使用竖线(|)作为字段定界符将表复制到 Client 端:

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

要复制到 zipfile 中,可以通过外部压缩程序通过管道传递输出:

COPY country TO PROGRAM 'gzip > /usr1/proj/bray/sql/country_data.gz';

以下是适合从STDIN复制到表中的数据示例:

AF      AFGHANISTAN
AL      ALBANIA
DZ      ALGERIA
ZM      ZAMBIA
ZW      ZIMBABWE

请注意,每行上的空白实际上是一个制表符。

以下是相同的数据,以二进制格式输出。通过 UnixUtilod -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

Compatibility

SQL 标准中没有COPY语句。

在 PostgreSQL 9.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选项的参数。

在 PostgreSQL 7.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' ]
上一章 首页 下一章