⌘+k ctrl+k
1.4 (LTS)
搜索快捷键 cmd + k | ctrl + k
COPY 语句

示例

将 CSV 文件读取到 lineitem 表中,使用自动检测的 CSV 选项

COPY lineitem FROM 'lineitem.csv';

将 CSV 文件读取到 lineitem 表中,使用手动指定的 CSV 选项

COPY lineitem FROM 'lineitem.csv' (DELIMITER '|');

将 Parquet 文件读取到 lineitem 表中

COPY lineitem FROM 'lineitem.pq' (FORMAT parquet);

将 JSON 文件读取到 lineitem 表中,使用自动检测的选项

COPY lineitem FROM 'lineitem.json' (FORMAT json, AUTO_DETECT true);

将 CSV 文件读取到 lineitem 表中,使用双引号

COPY lineitem FROM "lineitem.csv";

将 CSV 文件读取到 lineitem 表中,省略引号

COPY lineitem FROM lineitem.csv;

将表导出为 CSV 文件

COPY lineitem TO 'lineitem.csv' (FORMAT csv, DELIMITER '|', HEADER);

将表导出为 CSV 文件,使用双引号

COPY lineitem TO "lineitem.csv";

将表导出为 CSV 文件,省略引号

COPY lineitem TO lineitem.csv;

将查询结果写入 Parquet 文件

COPY (SELECT l_orderkey, l_partkey FROM lineitem) TO 'lineitem.parquet' (COMPRESSION zstd);

将数据库 db1 的全部内容复制到数据库 db2

COPY FROM DATABASE db1 TO db2;

仅复制模式(目录元素)而不复制任何数据

COPY FROM DATABASE db1 TO db2 (SCHEMA);

概览

COPY 用于在 DuckDB 和外部文件之间移动数据。COPY ... FROM 将数据从外部文件导入 DuckDB。COPY ... TO 将数据从 DuckDB 导出到外部文件。COPY 命令可用于 CSVPARQUETJSON 文件。

COPY ... FROM

COPY ... FROM 将数据从外部文件导入到现有表中。数据会被追加到表中已有的数据之后。文件中的列数必须与表 tbl 中的列数匹配,并且列内容必须能够转换为表的列类型。如果无法转换,则会抛出错误。

如果指定了列列表,COPY 将仅复制文件中指定列的数据。如果表中存在不在列列表中的列,COPY ... FROM 将为这些列插入默认值。

将无表头的逗号分隔文件 test.csv 的内容复制到 test 表中

COPY test FROM 'test.csv';

将带有表头的逗号分隔文件的内容复制到 category 表中

COPY category FROM 'categories.csv' (HEADER);

lineitem.tbl 的内容复制到 lineitem 表中,内容以管道符 (|) 分隔

COPY lineitem FROM 'lineitem.tbl' (DELIMITER '|');

lineitem.tbl 的内容复制到 lineitem 表中,自动检测分隔符、引号字符以及是否包含表头

COPY lineitem FROM 'lineitem.tbl' (AUTO_DETECT true);

将逗号分隔文件 names.csv 的内容读取到 category 表的 name 列中。该表的其他列将填充其默认值

COPY category(name) FROM 'names.csv';

将 Parquet 文件 lineitem.parquet 的内容读取到 lineitem 表中

COPY lineitem FROM 'lineitem.parquet' (FORMAT parquet);

将换行符分隔的 JSON 文件 lineitem.ndjson 的内容读取到 lineitem 表中

COPY lineitem FROM 'lineitem.ndjson' (FORMAT json);

将 JSON 文件 lineitem.json 的内容读取到 lineitem 表中

COPY lineitem FROM 'lineitem.json' (FORMAT json, ARRAY true);

如果将表达式放置在括号内,则可以用作 COPY ... FROM 命令的源。

将路径存储在变量中的文件内容读取到 lineitem 表中

SET VARIABLE source_file = 'lineitem.json';
COPY lineitem FROM (getvariable('source_file'));

将作为预处理语句参数提供的文件内容读取到 lineitem 表中

PREPARE v1 AS COPY lineitem FROM ($1);
EXECUTE v1('lineitem.json');

语法

为了确保与 PostgreSQL 的兼容性,DuckDB 接受不完全符合此处所示铁轨图的 COPY ... FROM 语句。例如,以下语句是有效的

COPY tbl FROM 'tbl.csv' WITH DELIMITER '|' CSV HEADER;

COPY ... TO

COPY ... TO 将数据从 DuckDB 导出到外部 CSV、Parquet、JSON 或 BLOB 文件。它与 COPY ... FROM 具有大致相同的选项集,但在 COPY ... TO 的情况下,选项指定了如何将文件写入磁盘。COPY ... TO 创建的任何文件都可以通过使用带有相似选项集的 COPY ... FROM 复制回数据库中。

COPY ... TO 函数调用时既可以指定表名,也可以指定查询。指定表名时,整个表的内容将被写入结果文件。指定查询时,将执行查询并将查询结果写入结果文件。

lineitem 表的内容复制到带有表头的 CSV 文件中

COPY lineitem TO 'lineitem.csv';

lineitem 表的内容复制到文件 lineitem.tbl 中,列以管道符 (|) 分隔,并包含表头行

COPY lineitem TO 'lineitem.tbl' (DELIMITER '|');

使用制表符分隔符创建无表头的 TSV 文件

COPY lineitem TO 'lineitem.tsv' (DELIMITER '\t', HEADER false);

lineitem 表的 l_orderkey 列复制到文件 orderkey.tbl

COPY lineitem(l_orderkey) TO 'orderkey.tbl' (DELIMITER '|');

将查询结果复制到文件 query.csv 中,包含带列名的表头

COPY (SELECT 42 AS a, 'hello' AS b) TO 'query.csv' (DELIMITER ',');

将查询结果复制到 Parquet 文件 query.parquet

COPY (SELECT 42 AS a, 'hello' AS b) TO 'query.parquet' (FORMAT parquet);

将查询结果复制到换行符分隔的 JSON 文件 query.ndjson

COPY (SELECT 42 AS a, 'hello' AS b) TO 'query.ndjson' (FORMAT json);

将查询结果复制到 JSON 文件 query.json

COPY (SELECT 42 AS a, 'hello' AS b) TO 'query.json' (FORMAT json, ARRAY true);

返回作为 COPY 语句一部分写入的文件及其列统计信息

COPY (SELECT l_orderkey, l_comment FROM lineitem) TO 'lineitem_part.parquet' (RETURN_STATS);
文件名 count file_size_bytes footer_size_bytes column_statistics partition_keys
lineitem_part.parquet 600572 8579141 1445 {'"l_comment"'={column_size_bytes=7642227, max=zzle. slyly, min=' Tiresias above the blit', null_count=0}, '"l_orderkey"'={column_size_bytes=935457, max=600000, min=1, null_count=0}} NULL

注意:对于嵌套列(例如结构体),列统计信息是为每个部分定义的。例如,如果我们有一个列 name STRUCT(field1 INTEGER, field2 INTEGER),则列统计信息将包含 name.field1name.field2 的统计信息。

如果将表达式放置在括号内,则可以用作 COPY ... TO 命令的目标。

将查询结果复制到路径存储在变量中的文件中

SET VARIABLE target_file = 'target_file.parquet';
COPY (SELECT 'hello world') TO (getvariable('target_file'));

复制到作为预处理语句参数提供的文件中

PREPARE v1 AS COPY (SELECT 42 AS i) to $1;
EXECUTE v1('file.csv');

表达式也可用于选项。使用存储在变量中的格式复制到文件

SET VARIABLE my_format = 'parquet';
COPY (SELECT 42 AS i) TO 'file' (FORMAT getvariable('my_format'));

COPY ... TO 选项

作为复制操作的一部分,可以提供零个或多个复制选项。WITH 说明符是可选的,但如果指定了任何选项,则必须使用括号。参数值可以在单引号内或不加单引号传递。任意表达式均可用于参数值。

任何布尔选项都可以通过多种方式启用或禁用。您可以写入 trueON1 来启用选项,并写入 falseOFF0 来禁用它。BOOLEAN 值也可以省略,例如仅传递 (HEADER),这种情况下默认为 true

除少数例外,以下选项适用于所有使用 COPY 写入的格式。

名称 描述 类型 默认值
FORMAT 指定要使用的复制函数。默认值根据文件扩展名选择(例如,.parquet 会导致写入/读取 Parquet 文件)。如果文件扩展名未知,则选择 CSV。原生 DuckDB 提供 CSVPARQUETJSON,但可以通过 extensions 添加额外的复制函数。 VARCHAR auto
USE_TMP_FILE 如果原始文件存在,是否首先写入临时文件 (target.csv.tmp)。这可以防止在写入被取消的情况下用损坏的文件覆盖现有文件。 BOOL auto
OVERWRITE_OR_IGNORE 是否允许在文件已存在时覆盖它们。仅在使用 PARTITION_BY 时有效。 BOOL false
OVERWRITE 当设置为 true 时,目标目录中的所有现有文件都将被删除(远程文件系统不支持)。仅在使用 PARTITION_BY 时有效。 BOOL false
APPEND 当设置为 true 且生成的文件名模式已存在时,路径将被重新生成,以确保不会覆盖任何现有文件。仅在使用 PARTITION_BY 时有效。 BOOL false
FILENAME_PATTERN 设置用于文件名的模式,可选择包含 {uuid} / {uuidv4}{uuidv7} 以填充生成的 UUID(分别为 v4 或 v7),以及 {i}(由递增索引替换)。仅在使用 PARTITION_BY 时有效。 VARCHAR auto
FILE_EXTENSION 设置应分配给生成文件(s)的文件扩展名。 VARCHAR auto
PER_THREAD_OUTPUT 当设置为 true 时,COPY 命令为每个线程生成一个文件,而不是生成总共一个文件。这允许更快的并行写入。 BOOL false
FILE_SIZE_BYTES 如果设置了此参数,COPY 过程将创建一个包含导出文件的目录。如果文件超过设定的限制(指定为字节数,如 1000,或人类可读格式,如 1k),则该过程会在目录中创建一个新文件。此参数与 PER_THREAD_OUTPUT 结合使用。请注意,大小仅作为近似值,文件偶尔会略微超过限制。 VARCHARBIGINT (空)
PARTITION_BY 使用 Hive 分区方案进行分区的列,请参见 分区写入部分 VARCHAR[] (空)
PRESERVE_ORDER 在复制操作期间是否 保留顺序。默认为 preserve_insertion_order 配置选项的值。 BOOL (*)
RETURN_FILES 是否在查询结果中包含创建的文件路径(作为 files VARCHAR[] 列)。 BOOL false
RETURN_STATS 是否返回作为 COPY 语句一部分写入的文件及其列统计信息。 BOOL false
WRITE_PARTITION_COLUMNS 是否将分区列写入文件。仅在使用 PARTITION_BY 时有效。 BOOL false

语法

为了确保与 PostgreSQL 的兼容性,DuckDB 接受不完全符合此处所示铁轨图的 COPY ... TO 语句。例如,以下语句是有效的

COPY (SELECT 42 AS x, 84 AS y) TO 'out.csv' WITH DELIMITER '|' CSV HEADER;

COPY FROM DATABASE ... TO

COPY FROM DATABASE ... TO 语句将全部内容从一个附加数据库复制到另一个附加数据库。这包括模式(Schema),包括约束、索引、序列、宏以及数据本身。

ATTACH 'db1.db' AS db1;
CREATE TABLE db1.tbl AS SELECT 42 AS x, 3 AS y;
CREATE MACRO db1.two_x_plus_y(x, y) AS 2 * x + y;

ATTACH 'db2.db' AS db2;
COPY FROM DATABASE db1 TO db2;
SELECT db2.two_x_plus_y(x, y) AS z FROM db2.tbl;
z
87

若仅复制 db1模式db2 而不复制数据,请在语句中添加 SCHEMA

COPY FROM DATABASE db1 TO db2 (SCHEMA);

语法

格式特定选项

CSV 选项

以下选项适用于写入 CSV 文件时。

名称 描述 类型 默认值
COMPRESSION 文件的压缩类型。默认情况下,这将根据文件扩展名自动检测(例如,file.csv.gz 将使用 gzipfile.csv.zst 将使用 zstdfile.csv 将使用 none)。选项为 nonegzipzstd VARCHAR auto
DATEFORMAT 指定写入日期时使用的日期格式。请参见 日期格式 VARCHAR (空)
DELIMSEP 用于分隔每一行中各列的字符。 VARCHAR ,
ESCAPE 应出现在与 quote 值匹配的字符之前的字符。 VARCHAR "
FORCE_QUOTE 总是需要添加引号的列列表,即使不需要时也是如此。 VARCHAR[] []
HEADER 是否为 CSV 文件写入表头。 BOOL true
NULLSTR 写入以表示 NULL 值的字符串。 VARCHAR (空)
PREFIX 使用指定字符串为 CSV 文件添加前缀。此选项必须与 SUFFIX 结合使用,并要求将 HEADER 设置为 false VARCHAR (空)
SUFFIX 将指定字符串作为后缀附加到 CSV 文件。此选项必须与 PREFIX 结合使用,并要求将 HEADER 设置为 false VARCHAR (空)
QUOTE 当数据值被引用时使用的引号字符。 VARCHAR "
TIMESTAMPFORMAT 指定写入时间戳时使用的日期格式。请参见 日期格式 VARCHAR (空)

Parquet 选项

以下选项适用于写入 Parquet 文件时。

名称 描述 类型 默认值
COMPRESSION 要使用的压缩格式(uncompressedsnappygzipzstdbrotlilz4lz4_raw)。 VARCHAR snappy
COMPRESSION_LEVEL 压缩级别,设置范围在 1(压缩率最低,速度最快)到 22(压缩率最高,速度最慢)。仅支持 zstd 压缩。 BIGINT 3
FIELD_IDS 每列的 field_id。传递 auto 以尝试自动推断。 STRUCT (空)
ROW_GROUP_SIZE_BYTES 每个行组的目标大小。您可以传递人类可读字符串(如 2MB)或整数(即字节数)。此选项仅在执行了 SET preserve_insertion_order = false; 时使用,否则将被忽略。 BIGINT row_group_size * 1024
ROW_GROUP_SIZE 每个行组的目标大小,即行数。 BIGINT 122880
ROW_GROUPS_PER_FILE 如果当前文件具有指定的行组数,则创建一个新的 Parquet 文件。如果启用了多个线程,文件中的行组数可能会略微超过指定数量以限制锁定数量——这类似于 FILE_SIZE_BYTES 的行为。但是,如果设置了 per_thread_output,则每个文件仅由一个线程写入,它将再次变得准确。 BIGINT (空)
PARQUET_VERSION 要使用的 Parquet 版本(V1, V2)。 VARCHAR V1

FIELD_IDS 的一些示例如下。

自动分配 field_ids

COPY
    (SELECT 128 AS i)
    TO 'my.parquet'
    (FIELD_IDS 'auto');

将列 ifield_id 设置为 42

COPY
    (SELECT 128 AS i)
    TO 'my.parquet'
    (FIELD_IDS {i: 42});

将列 ifield_id 设置为 42,将列 j 设置为 43

COPY
    (SELECT 128 AS i, 256 AS j)
    TO 'my.parquet'
    (FIELD_IDS {i: 42, j: 43});

将列 my_structfield_id 设置为 43,并将列 i(嵌套在 my_struct 内部)设置为 43

COPY
    (SELECT {i: 128} AS my_struct)
    TO 'my.parquet'
    (FIELD_IDS {my_struct: {__duckdb_field_id: 42, i: 43}});

将列 my_listfield_id 设置为 42,并将列 element(列表子项的默认名称)设置为 43

COPY
    (SELECT [128, 256] AS my_list)
    TO 'my.parquet'
    (FIELD_IDS {my_list: {__duckdb_field_id: 42, element: 43}});

将列 my_mapfield_id 设置为 42,并将列 keyvalue(映射子项的默认名称)设置为 43 和 44

COPY
    (SELECT MAP {'key1' : 128, 'key2': 256} my_map)
    TO 'my.parquet'
    (FIELD_IDS {my_map: {__duckdb_field_id: 42, key: 43, value: 44}});

JSON 选项

以下选项适用于写入 JSON 文件时。

名称 描述 类型 默认值
ARRAY 是否写入 JSON 数组。如果为 true,则写入记录的 JSON 数组;如果为 false,则写入换行符分隔的 JSON BOOL false
COMPRESSION 文件的压缩类型。默认情况下,这将根据文件扩展名自动检测(例如,file.json.gz 将使用 gzipfile.json.zst 将使用 zstdfile.json 将使用 none)。选项为 nonegzipzstd VARCHAR auto
DATEFORMAT 指定写入日期时使用的日期格式。请参见 日期格式 VARCHAR (空)
TIMESTAMPFORMAT 指定写入时间戳时使用的日期格式。请参见 日期格式 VARCHAR (空)

将列 hello 的值设置为 QUACK! 并将结果输出到 quack.json

COPY (SELECT 'QUACK!' AS hello) TO 'quack.json';
--RETURNS: {"hello":"QUACK!"}

将列 num_list 的值设置为 [1,2,3] 并将结果输出到 numbers.json

COPY (SELECT [1, 2, 3] AS num_list) TO 'numbers.json';
--RETURNS: {"num_list":[1,2,3]}

将列 compression_type 的值设置为 gzip_explicit 并以显式压缩方式将结果输出到 compression.json.gz

COPY (SELECT 'gzip_explicit' AS compression_type) TO 'explicit_compression.json' (FORMAT json, COMPRESSION 'GZIP');
-- RETURNS: {"compression_type":"gzip_explicit"}

将单行的所有值设置为作为嵌套数组返回到 array_true.json

COPY (SELECT 1 AS id, 'Alice' AS name, [1, 2, 3] AS numbers
      UNION ALL
      SELECT 2, 'Bob', [4, 5, 6] AS numbers)
TO 'array_true.json' (FORMAT json, ARRAY true);

-- RETURNS: 
/*
[
	{"id":1,"name":"Alice","numbers":[1,2,3]},
	{"id":2,"name":"Bob","numbers":[1,2,3]}
]
*/

将单行的所有值设置为作为非嵌套数组返回到 array_false.json

COPY (SELECT 1 AS id, 'Alice' AS name, [1, 2, 3] AS numbers
      UNION ALL
      SELECT 2, 'Bob', [4, 5, 6] AS numbers)
TO 'array_false.json' (FORMAT json, ARRAY false);

-- RETURNS:
/*
{"id":1,"name":"Alice","numbers":[1,2,3]}
{"id":2,"name":"Bob","numbers":[4,5,6]}
*/

BLOB 选项

BLOB 格式选项允许您将 DuckDB 表的单个列选择到 .blob 文件中。该列必须强制转换为 BLOB 数据类型。有关类型转换的详细信息,请参见 类型转换操作矩阵

以下选项适用于写入 BLOB 文件时。

名称 描述 类型 默认值
COMPRESSION 文件的压缩类型。默认情况下,这将根据文件扩展名自动检测(例如,file.blob.gz 将使用 gzipfile.blob.zst 将使用 zstdfile.blob 将使用 none)。选项为 nonegzipzstd VARCHAR auto

将字符串值 foo 类型转换为 BLOB 数据类型,并将结果输出到 blob_output.blob

COPY (select 'foo'::BLOB) TO 'blob_output.blob' (FORMAT BLOB);

将字符串值 foo 类型转换为 BLOB 数据类型,并使用 gzip 压缩将结果输出到 blob_output_gzip.blob.gz

COPY (select 'foo'::BLOB) TO 'blob_output_gzip.blob' (FORMAT BLOB, COMPRESSION 'GZIP');

限制

COPY 不支持在表之间进行复制。要在表之间复制,请使用 INSERT 语句

INSERT INTO tbl2
    FROM tbl1;
© 2025 DuckDB 基金会,阿姆斯特丹,荷兰
行为准则 商标使用指南