COPY 문
COPY 문 (COPY Statement)
COPY는 DuckDB와 외부 파일 사이에서 데이터를 옮길 때 쓰는 명령이에요. DuckDB와 외부 파일 사이의 데이터 이동을 담당하죠. COPY ... FROM은 외부 파일에서 DuckDB로 데이터를 가져오고, COPY ... TO는 DuckDB에서 외부 파일로 데이터를 써요. COPY 명령은 CSV, PARQUET, JSON 파일에 사용할 수 있어요.
출처: 문서
본문
Examples
자동 감지되는 CSV 옵션을 사용해 CSV 파일을 lineitem 테이블로 읽어요.
COPY lineitem FROM 'lineitem.csv';
수동으로 지정한 CSV 옵션을 사용해 CSV 파일을 lineitem 테이블로 읽어요.
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 ... 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'));
준비된 문(statement)의 파라미터로 제공된 파일의 내용을 lineitem 테이블로 읽어요.
PREPARE v1 AS COPY lineitem FROM ($1);
EXECUTE v1('lineitem.json');
Syntax
PostgreSQL과의 호환성을 위해 DuckDB는 여기 표시된 railroad 다이어그램을 완전히 따르지 않는
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);
| filename | 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 |
참고로 중첩 열(예: struct)의 경우 각 부분에 대해 열 통계가 정의돼요. 예를 들어 name STRUCT(field1 INTEGER, field2 INTEGER) 열이 있으면 열 통계에 name.field1과 name.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 옵션
복사 작업의 일부로 복사 옵션을 0개 이상 제공할 수 있어요. WITH 지정자는 선택이지만, 옵션을 지정하면 괄호가 필요해요. 파라미터 값은 작은따옴표로 감싸거나 감싸지 않고 전달할 수 있어요. 파라미터 값에는 임의의 표현식을 사용할 수 있어요.
Boolean인 모든 옵션은 여러 방식으로 켜고 끌 수 있어요. true, ON, 또는 1은 활성화, false, OFF, 또는 0은 비활성화를 의미해요. BOOLEAN 값은 생략할 수도 있는데, 예를 들어 (HEADER)만 넘기면 true로 간주돼요.
몇 가지 예외를 빼고 아래 옵션은 COPY로 쓰는 모든 포맷에 적용돼요.
| Name | Description | Type | Default |
|---|---|---|---|
FORMAT |
사용할 복사 함수를 지정합니다. 기본값은 파일 확장자로 선택됩니다 (예: .parquet는 Parquet 파일 쓰기/읽기를 의미). 파일 확장자를 모르면 CSV가 선택됩니다. 기본 DuckDB는 CSV, PARQUET, JSON을 제공하지만 [extensions]({% link docs/current/extensions/overview.md %})로 추가 복사 함수를 추가할 수 있습니다. |
VARCHAR |
auto |
USE_TMP_FILE |
원본 파일이 이미 존재하면 먼저 임시 파일(target.csv.tmp)에 쓸지 여부. 쓰기가 취소될 때 기존 파일을 깨진 파일로 덮어쓰는 것을 방지합니다. |
BOOL |
auto |
OVERWRITE_OR_IGNORE |
파일이 이미 존재하면 덮어쓰기를 허용할지 여부. PARTITION_BY, PER_THREAD_OUTPUT, FILE_SIZE_BYTES처럼 여러 파일을 쓰는 옵션과 함께 쓸 때만 효과가 있습니다. |
BOOL |
false |
OVERWRITE |
true면 대상 디렉터리 안의 모든 기존 파일을 제거합니다 (원격 파일시스템에서는 미지원). PARTITION_BY, PER_THREAD_OUTPUT, FILE_SIZE_BYTES처럼 여러 파일을 쓰는 옵션과 함께 쓸 때만 효과가 있습니다. |
BOOL |
false |
APPEND |
true면 이미 존재하는 파일 이름 패턴이 생성된 경우 기존 파일을 덮어쓰지 않도록 경로를 재생성합니다. PARTITION_BY, PER_THREAD_OUTPUT, FILE_SIZE_BYTES처럼 여러 파일을 쓰는 옵션과 함께 쓸 때만 효과가 있습니다. |
BOOL |
false |
FILENAME_PATTERN |
파일 이름에 사용할 패턴을 설정합니다. 생성된 [UUID]({% link docs/current/sql/data_types/numeric.md %}#universally-unique-identifiers-uuids) (각각 v4 또는 v7)로 채워질 {uuid} / {uuidv4} 또는 {uuidv7}, 그리고 증가 인덱스로 치환되는 {i}를 포함할 수 있습니다. PARTITION_BY, PER_THREAD_OUTPUT, FILE_SIZE_BYTES처럼 여러 파일을 쓰는 옵션과 함께 쓸 때만 효과가 있습니다. |
VARCHAR |
auto |
FILE_EXTENSION |
생성된 파일에 할당할 파일 확장자를 설정합니다. | VARCHAR |
auto |
PER_THREAD_OUTPUT |
true면 COPY 명령이 총 하나의 파일이 아니라 스레드당 하나의 파일을 생성합니다. 더 빠른 병렬 쓰기가 가능해집니다. |
BOOL |
false |
FILE_SIZE_BYTES |
이 파라미터를 설정하면 COPY 프로세스가 내보낸 파일들을 담을 디렉터리를 만듭니다. 파일이 설정된 한도(바이트(1000) 또는 사람이 읽기 쉬운 형식(1k)으로 지정)를 초과하면 프로세스가 디렉터리에 새 파일을 만듭니다. PER_THREAD_OUTPUT과 함께 동작합니다. 크기는 근사치로 사용되며 파일이 가끔 한도를 약간 넘을 수 있습니다. |
VARCHAR 또는 BIGINT |
(empty) |
PARTITION_BY |
Hive 파티셔닝 스킴으로 파티셔닝할 열입니다. [partitioned writes 섹션]({% link docs/current/data/partitioning/partitioned_writes.md %}) 참고. | VARCHAR[] |
(empty) |
PRESERVE_ORDER |
복사 작업 중 [순서 보존]({% link docs/current/sql/dialect/order_preservation.md %}) 여부. preserve_insertion_order [설정 옵션]({% link docs/current/configuration/overview.md %})의 값으로 기본 설정됩니다. |
BOOL |
(*) |
RETURN_FILES |
생성된 파일 경로를 (쿼리 결과의 files VARCHAR[] 열로) 포함할지 여부. |
BOOL |
false |
RETURN_STATS |
COPY 문의 일부로 쓰인 파일들과 그 열 통계를 반환할지 여부. |
BOOL |
false |
WRITE_PARTITION_COLUMNS |
파티션 열을 파일에 쓸지 여부. PARTITION_BY와 함께 쓸 때만 효과가 있습니다. |
BOOL |
false |
Syntax
PostgreSQL과의 호환성을 위해 DuckDB는 여기 표시된 railroad 다이어그램을 완전히 따르지 않는
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);
Syntax
포맷별 옵션
CSV 옵션
아래 옵션은 CSV 파일을 쓸 때 적용돼요.
| Name | Description | Type | Default |
|---|---|---|---|
COMPRESSION |
파일의 압축 타입. 기본적으로 파일 확장자에서 자동 감지됩니다 (예: file.csv.gz는 gzip, file.csv.zst는 zstd, file.csv는 none). 옵션은 none, gzip, zstd. |
VARCHAR |
auto |
DATEFORMAT |
날짜를 쓸 때 사용할 날짜 포맷을 지정합니다. [Date Format]({% link docs/current/sql/functions/dateformat.md %}) 참고. | VARCHAR |
(empty) |
DELIM 또는 SEP |
각 행 안에서 열을 구분하기 위해 쓰이는 문자. | VARCHAR |
, |
NEW_LINE |
각 행을 구분하기 위해 쓰이는 문자. 이스케이프된 문자열 사용, 예: E'\x1e' |
VARCHAR |
\n |
ESCAPE |
quote 값과 일치하는 문자 앞에 나타나야 하는 문자. |
VARCHAR |
" |
FORCE_QUOTE |
필요하지 않아도 항상 인용을 추가할 열 목록. | VARCHAR[] |
[] |
HEADER |
CSV 파일에 헤더를 쓸지 여부. | BOOL |
true |
NULLSTR |
NULL 값을 나타내기 위해 쓰이는 문자열. |
VARCHAR |
(empty) |
PREFIX |
CSV 파일 앞에 지정된 문자열을 붙입니다. SUFFIX와 함께 사용해야 하며 HEADER를 false로 설정해야 합니다. |
VARCHAR |
(empty) |
SUFFIX |
CSV 파일에 지정된 문자열을 접미사로 덧붙입니다. PREFIX와 함께 사용해야 하며 HEADER를 false로 설정해야 합니다. |
VARCHAR |
(empty) |
QUOTE |
데이터 값을 인용할 때 사용할 인용 문자. | VARCHAR |
" |
TIMESTAMPFORMAT |
타임스탬프를 쓸 때 사용할 날짜 포맷을 지정합니다. [Date Format]({% link docs/current/sql/functions/dateformat.md %}) 참고. | VARCHAR |
(empty) |
Parquet 옵션
아래 옵션은 Parquet 파일을 쓸 때 적용돼요.
| Name | Description | Type | Default |
|---|---|---|---|
COMPRESSION |
사용할 압축 포맷 (uncompressed, snappy, gzip, zstd, brotli, lz4, lz4_raw). |
VARCHAR |
snappy |
COMPRESSION_LEVEL |
1(가장 낮은 압축, 가장 빠름)과 22(가장 높은 압축, 가장 느림) 사이의 압축 레벨. zstd 압축에서만 지원됩니다. | BIGINT |
3 |
FIELD_IDS |
각 열의 field_id. 자동 추론하려면 auto를 넘기세요. |
STRUCT |
(empty) |
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 |
(empty) |
PARQUET_VERSION |
사용할 Parquet 버전 (V1, V2). |
VARCHAR |
V1 |
CHUNK_SIZE |
ROW_GROUP_SIZE의 별칭. |
BIGINT |
122880 |
KV_METADATA |
파일 footer에 포함할 사용자 정의 키-값 메타데이터. 키에서 값으로의 STRUCT로 제공합니다. BLOB 값은 원시 바이트로 쓰이고, 다른 값은 문자열로 캐스팅됩니다. |
STRUCT |
(empty) |
SHREDDING |
[VARIANT]({% link docs/current/sql/data_types/variant.md %}) 열 이름을 그들이 shredding되어야 할 타입으로 매핑하는 STRUCT. 예: {variant_col: 'STRUCT(name VARCHAR, age INTEGER)'}. VARIANT 열의 타입 있는(shredded) 저장을 활성화합니다. |
STRUCT |
(empty) |
DICTIONARY_SIZE_LIMIT |
딕셔너리 인코딩에 사용되는 딕셔너리의 최대 크기(고유 값 수). 0으로 설정하면 딕셔너리 인코딩을 비활성화합니다. |
BIGINT |
ROW_GROUP_SIZE / 5 |
WRITE_BLOOM_FILTER |
읽는 쪽이 행 그룹을 건너뛰게 하는 Bloom filters를 쓸지 여부. | BOOLEAN |
true |
BLOOM_FILTER_FALSE_POSITIVE_RATIO |
쓰여진 Bloom filter의 목표 거짓 양성 비율. | DOUBLE |
0.01 |
GEOPARQUET_VERSION |
지오메트리 열에 쓸 GeoParquet 메타데이터 버전 (NONE, V1, V2, BOTH). NONE는 GeoParquet 메타데이터를 비활성화합니다. |
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를 43으로 설정하기:
COPY
(SELECT 128 AS i, 256 AS j)
TO 'my.parquet'
(FIELD_IDS {i: 42, j: 43});
열 my_struct의 field_id를 42로, (my_struct 안에 중첩된) 열 i를 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 열을 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 열을 각각 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 파일을 쓸 때 적용돼요.
| Name | Description | Type | Default |
|---|---|---|---|
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 |
날짜를 쓸 때 사용할 날짜 포맷을 지정합니다. [Date Format]({% link docs/current/sql/functions/dateformat.md %}) 참고. | VARCHAR |
(empty) |
TIMESTAMPFORMAT |
타임스탬프를 쓸 때 사용할 날짜 포맷을 지정합니다. [Date Format]({% link docs/current/sql/functions/dateformat.md %}) 참고. | VARCHAR |
(empty) |
열 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 데이터 타입으로 캐스팅해야 해요. 타입 캐스팅에 대한 자세한 내용은 [Casting Operations Matrix]({% link docs/current/sql/data_types/typecasting.md %}#Casting-Operations-Matrix)를 참고하세요.
아래 옵션은 BLOB 파일을 쓸 때 적용돼요.
| Name | Description | Type | Default |
|---|---|---|---|
COMPRESSION |
파일의 압축 타입. 기본적으로 파일 확장자에서 자동 감지됩니다 (예: file.blob.gz는 gzip, file.blob.zst는 zstd, file.blob은 none). 옵션은 none, gzip, zstd. |
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');
Limitation
COPY는 테이블 간 복사를 지원하지 않아요. 테이블 간 복사에는 [INSERT 문]({% link docs/current/sql/statements/insert.md %})을 사용하세요.
INSERT INTO tbl2
FROM tbl1;