示例
将 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
命令可用于 CSV
、PARQUET
和 JSON
文件。
COPY ... FROM
COPY ... FROM
将数据从外部文件导入到现有表中。数据将追加到表中已有的数据。文件中的列数必须与表 table_name
中的列数匹配,并且列内容必须可转换为表的列类型。如果无法转换,将抛出错误。
如果指定了列列表,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);
语法
为确保与 PostgreSQL 兼容,DuckDB 接受不完全符合此处所示铁路图的
COPY ... FROM
语句。例如,以下是一个有效语句:COPY tbl FROM 'tbl.csv' WITH DELIMITER '|' CSV HEADER;
COPY ... TO
COPY ... TO
将数据从 DuckDB 导出到外部 CSV 或 Parquet 文件。它与 COPY ... FROM
大致有相同的选项集,但在 COPY ... TO
的情况下,这些选项指定了文件应如何写入磁盘。通过使用类似选项集的 COPY ... FROM
,任何由 COPY ... TO
创建的文件都可以被复制回数据库。
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.field1
和 name.field2
的统计信息。
COPY ... TO
选项
可以作为复制操作的一部分提供零个或多个复制选项。WITH
指定符是可选的,但如果指定了任何选项,则括号是必需的。参数值可以带或不带单引号。
任何布尔选项都可以通过多种方式启用或禁用。您可以写入 true
、ON
或 1
来启用选项,写入 false
、OFF
或 0
来禁用选项。BOOLEAN
值也可以省略,例如,仅传递 (HEADER)
,在这种情况下假定为 true
。
除少数例外,以下选项适用于所有使用 COPY
写入的格式。
名称 | 描述 | 类型 | 默认值 |
---|---|---|---|
FORMAT(格式) |
指定要使用的复制函数。默认值从文件扩展名中选择(例如,.parquet 导致写入/读取 Parquet 文件)。如果文件扩展名未知,则选择 CSV 。原版 DuckDB 提供 CSV 、PARQUET 和 JSON ,但可以通过扩展 添加额外的复制函数。 |
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(文件扩展名) |
设置应分配给生成文件(或多个文件)的文件扩展名。 | VARCHAR |
auto(自动) |
PER_THREAD_OUTPUT(按线程输出) |
当为 true 时,COPY 命令为每个线程生成一个文件,而不是总共一个文件。这允许更快的并行写入。 |
BOOL |
false(否) |
FILE_SIZE_BYTES(文件大小字节) |
如果设置了此参数,COPY 进程将创建一个目录,其中包含导出的文件。如果文件超过设定的限制(以字节为单位指定,如 1000 或以人类可读格式指定,如 1k ),进程将在目录中创建一个新文件。此参数与 PER_THREAD_OUTPUT 结合使用。请注意,大小用作近似值,文件偶尔可能会略微超过限制。 |
VARCHAR 或 BIGINT |
(空) |
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
语句将一个已附加数据库的全部内容复制到另一个已附加数据库。这包括模式,例如约束、索引、序列、宏和数据本身。
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 将使用 gzip ,file.csv.zst 将使用 zstd ,file.csv 将使用 none )。选项包括 none 、gzip 、zstd 。 |
VARCHAR |
auto(自动) |
DATEFORMAT(日期格式) |
指定写入日期时使用的日期格式。请参阅日期格式。 | VARCHAR |
(空) |
DELIM 或 SEP (分隔符) |
写入以分隔每行中列的字符。 | 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(压缩) |
要使用的压缩格式(uncompressed 、snappy 、gzip 、zstd 、brotli 、lz4 、lz4_raw )。 |
VARCHAR |
snappy |
COMPRESSION_LEVEL(压缩级别) |
压缩级别,设置在 1(最低压缩,最快)到 22(最高压缩,最慢)之间。仅支持 zstd 压缩。 | BIGINT |
3 |
FIELD_IDS(字段 ID) |
每个列的 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 版本) |
要使用的 parquet 版本(V1 、V2 )。 |
VARCHAR |
V1 |
FIELD_IDS
的一些示例如下。
自动分配 field_ids
COPY
(SELECT 128 AS i)
TO 'my.parquet'
(FIELD_IDS 'auto');
将列 i
的 field_id
设置为 42
COPY
(SELECT 128 AS i)
TO 'my.parquet'
(FIELD_IDS {i: 42});
将列 i
的 field_id
设置为 42,将列 j
的 field_id
设置为 43
COPY
(SELECT 128 AS i, 256 AS j)
TO 'my.parquet'
(FIELD_IDS {i: 42, j: 43});
将列 my_struct
的 field_id
设置为 43,并将列 i
(嵌套在 my_struct
中)的 field_id
设置为 43
COPY
(SELECT {i: 128} AS my_struct)
TO 'my.parquet'
(FIELD_IDS {my_struct: {__duckdb_field_id: 42, i: 43}});
将列 my_list
的 field_id
设置为 42,并将列 element
(列表子项的默认名称)的 field_id
设置为 43
COPY
(SELECT [128, 256] AS my_list)
TO 'my.parquet'
(FIELD_IDS {my_list: {__duckdb_field_id: 42, element: 43}});
将列 my_map
的 field_id
设置为 42,并将列 key
和 value
(映射子项的默认名称)的 field_id
分别设置为 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 将使用 gzip ,file.json.zst 将使用 zstd ,file.json 将使用 none )。选项包括 none 、gzip 、zstd 。 |
VARCHAR |
auto(自动) |
DATEFORMAT(日期格式) |
指定写入日期时使用的日期格式。请参阅日期格式。 | VARCHAR |
(空) |
TIMESTAMPFORMAT(时间戳格式) |
指定写入时间戳时使用的日期格式。请参阅日期格式。 | VARCHAR |
(空) |
限制
COPY
不支持表之间的数据复制。要在表之间复制,请使用 INSERT 语句
。
INSERT INTO tbl2
FROM tbl1;