COPY — 파일과 테이블 사이의 데이터 복사
COPY — 파일과 테이블 사이의 데이터 복사
COPY 명령은 PostgreSQL 테이블과 표준 파일시스템 파일 사이에서 데이터를 이동시키는 명령이에요. COPY TO는 테이블의 내용을 파일로 복사하고, COPY FROM은 파일의 데이터를 테이블로 복사해요. 대량 데이터의 빠른 입출력에 핵심적인 도구예요.
출처: PostgreSQL 문서
본문
Synopsis
COPY table_name [ ( column_name [, ...] ) ]
FROM { 'filename' | PROGRAM 'command' | STDIN }
[ [ WITH ] ( option [, ...] ) ]
[ WHERE condition ]
COPY { table_name [ ( column_name [, ...] ) ] | ( query ) }
TO { 'filename' | PROGRAM 'command' | STDOUT }
[ [ WITH ] ( option [, ...] ) ]
where option can be one of:
FORMAT format_name
FREEZE [ boolean ]
DELIMITER 'delimiter_character'
NULL 'null_string'
DEFAULT 'default_string'
HEADER [ boolean | MATCH ]
QUOTE 'quote_character'
ESCAPE 'escape_character'
FORCE_QUOTE { ( column_name [, ...] ) | * }
FORCE_NOT_NULL { ( column_name [, ...] ) | * }
FORCE_NULL { ( column_name [, ...] ) | * }
ON_ERROR error_action
REJECT_LIMIT maxerror
ENCODING 'encoding_name'
LOG_VERBOSITY verbosity
Description
COPY는 PostgreSQL 테이블과 표준 파일시스템 파일 사이에서 데이터를 이동시켜요. COPY TO는 테이블의 내용을 파일 로 복사하고, COPY FROM은 파일 에서 테이블로 데이터를 복사해요 (이미 테이블에 있는 내용에 데이터를 추가해요). COPY TO는 SELECT 쿼리의 결과도 복사할 수 있어요.
컬럼 목록이 지정되면 COPY TO는 지정된 컬럼의 데이터만 파일로 복사해요. COPY FROM의 경우 파일의 각 필드가 순서대로 지정된 컬럼에 삽입돼요. COPY FROM 컬럼 목록에 지정되지 않은 테이블 컬럼들은 기본값을 받아요.
파일 이름이 있는 COPY는 PostgreSQL 서버가 파일에서 직접 읽거나 파일에 직접 쓰도록 지시해요. 파일은 PostgreSQL 사용자(서버가 실행되는 사용자 ID)가 접근할 수 있어야 하며, 이름은 서버의 관점에서 지정되어야 해요. PROGRAM을 지정하면 서버가 주어진 명령을 실행하고 프로그램의 표준 출력에서 읽거나, 프로그램의 표준 입력에 씁니다. 명령은 서버의 관점에서 지정되어야 하고, PostgreSQL 사용자가 실행할 수 있어야 해요. STDIN 또는 STDOUT을 지정하면 데이터는 클라이언트와 서버 사이의 연결을 통해 전송돼요.
각 백엔드가 실행 중인 COPY의 진행 상황을 pg_stat_progress_copy 뷰에서 보고해요. 자세한 내용은 27.4.3 절을 참고해요.
기본적으로 COPY는 처리 중 오류를 만나면 실패해요. 전체 파일을 최선으로(best-effort) 로드하려는 사용 사례에서는 ON_ERROR 절을 사용해 다른 동작을 지정할 수 있어요.
Parameters
table_name
기존 테이블의 이름이에요 (선택적으로 스키마 한정).
column_name
복사할 컬럼의 선택적인 목록이에요. 컬럼 목록을 지정하지 않으면 생성 컬럼을 제외한 테이블의 모든 컬럼이 복사돼요.
query
결과가 복사될 SELECT, VALUES, INSERT, UPDATE, DELETE, 또는 MERGE 명령이에요. 쿼리 주위에 괄호가 필요하다는 점을 참고하세요.
INSERT, UPDATE, DELETE, MERGE 쿼리의 경우 RETURNING 절이 제공되어야 하며, 대상 관계는 조건부 규칙이나 ALSO 규칙, 또는 여러 문으로 확장되는 INSTEAD 규칙을 가지면 안 돼요.
filename
입력 또는 출력 파일의 경로 이름이에요. 입력 파일 이름은 절대 경로나 상대 경로일 수 있지만, 출력 파일 이름은 절대 경로여야 해요. Windows 사용자는 E'' 문자열을 사용하고 경로 이름의 모든 백슬래시를 두 배로 늘려야 할 수 있어요.
PROGRAM
실행할 명령이에요. COPY FROM에서는 입력이 명령의 표준 출력에서 읽히고, COPY TO에서는 출력이 명령의 표준 입력에 쓰여져요.
명령은 셸에 의해 호출되므로, 신뢰할 수 없는 출처에서 온 인자를 전달해야 한다면 셸에 특별한 의미가 있을 수 있는 특수 문자를 제거하거나 이스케이프하는 데 주의해야 해요. 보안상의 이유로 고정된 명령 문자열을 사용하는 것이 가장 좋으며, 적어도 그 안에 사용자 입력을 포함시키는 것은 피해야 해요.
STDIN
입력이 클라이언트 애플리케이션에서 온다는 것을 지정해요.
STDOUT
출력이 클라이언트 애플리케이션으로 간다는 것을 지정해요.
boolean
선택한 옵션을 켤지 끌지 지정해요. 옵션을 활성화하려면 TRUE, ON, 1을, 비활성화하려면 FALSE, OFF, 0을 쓸 수 있어요. boolean 값은 생략할 수도 있는데, 생략하면 TRUE로 간주돼요.
FORMAT
읽거나 쓸 데이터 형식을 선택해요. text, csv (Comma Separated Values), 또는 binary예요. 기본값은 text예요. 세부 사항은 아래의 File Formats를 참고해요.
FREEZE
행이 이미 동결된 상태로 데이터를 복사하도록 요청해요. 마치 VACUUM FREEZE 명령을 실행한 후의 상태처럼요. 이는 초기 데이터 로딩을 위한 성능 옵션으로 의도된 것이에요. 행은 로드되는 테이블이 현재 서브트랜잭션에서 생성되거나 잘렸고, 열려 있는 커서가 없으며, 이 트랜잭션이 보유한 오래된 스냅샷이 없을 때만 동결돼요. 현재 파티션 테이블이나 외부 테이블에 COPY FREEZE를 수행하는 것은 불가능해요. 이 옵션은 COPY FROM에서만 허용돼요.
다른 모든 세션은 데이터가 성공적으로 로드되는 즉시 그 데이터를 볼 수 있다는 점을 참고하세요. 이는 MVCC 가시성의 정상적인 규칙을 위반하며, 사용자는 이것이 초래할 수 있는 잠재적 문제를 알고 있어야 해요.
DELIMITER
파일의 각 행(줄) 안에서 컬럼을 구분하는 문자를 지정해요. 기본값은 text 형식에서 탭 문자, CSV 형식에서 쉼표예요. 단일 1바이트 문자여야 해요. binary 형식을 사용할 때는 이 옵션이 허용되지 않아요.
NULL
null 값을 나타내는 문자열을 지정해요. 기본값은 text 형식에서 \N (백슬래시-N), CSV 형식에서 따옴표 없는 빈 문자열이에요. null과 빈 문자열을 구분하고 싶지 않은 경우 text 형식에서도 빈 문자열을 선호할 수 있어요. binary 형식을 사용할 때는 이 옵션이 허용되지 않아요.
참고 (Note)
COPY FROM을 사용할 때 이 문자열과 일치하는 모든 데이터 항목은 null 값으로 저장되므로,COPY TO에서 사용한 것과 같은 문자열을 사용해야 해요.
DEFAULT
기본값을 나타내는 문자열을 지정해요. 입력 파일에서 문자열이 발견될 때마다 해당 컬럼의 기본값이 사용돼요. 이 옵션은 COPY FROM에서만, 그리고 binary 형식을 사용하지 않을 때만 허용돼요.
HEADER
파일에 파일의 각 컬럼 이름이 있는 헤더 줄이 포함되어 있음을 지정해요. 출력 시 첫 줄은 테이블의 컬럼 이름을 포함해요. 입력 시 true (또는 동등한 Boolean 값)로 설정되면 첫 줄은 버려져요. MATCH로 설정되면 헤더 줄의 컬럼 수와 이름이 테이블의 실제 컬럼 이름과 순서까지 일치해야 해요. 그렇지 않으면 오류가 발생해요. binary 형식을 사용할 때는 이 옵션이 허용되지 않아요. MATCH 옵션은 COPY FROM 명령에서만 유효해요.
QUOTE
데이터 값이 인용될 때 사용할 인용 문자를 지정해요. 기본값은 큰따옴표예요. 단일 1바이트 문자여야 해요. 이 옵션은 CSV 형식을 사용할 때만 허용돼요.
ESCAPE
QUOTE 값과 일치하는 데이터 문자 앞에 나타나야 하는 문자를 지정해요. 기본값은 QUOTE 값과 동일해요 (그래서 데이터에 인용 문자가 나타나면 인용 문자가 두 배가 돼요). 단일 1바이트 문자여야 해요. 이 옵션은 CSV 형식을 사용할 때만 허용돼요.
FORCE_QUOTE
지정된 각 컬럼의 모든 비-NULL 값에 대해 인용이 사용되도록 강제해요. NULL 출력은 절대 인용되지 않아요. *를 지정하면 모든 컬럼의 비-NULL 값이 인용돼요. 이 옵션은 COPY TO에서만, 그리고 CSV 형식을 사용할 때만 허용돼요.
FORCE_NOT_NULL
지정된 컬럼의 값을 null 문자열과 대조하지 마세요. null 문자열이 비어 있는 기본 경우, 이는 인용되지 않은 빈 값이라도 null이 아닌 0길이 문자열로 읽힌다는 뜻이에요. *를 지정하면 옵션이 모든 컬럼에 적용돼요. 이 옵션은 COPY FROM에서만, 그리고 CSV 형식을 사용할 때만 허용돼요.
FORCE_NULL
지정된 컬럼의 값을, 인용되었더라도 null 문자열과 대조하고, 일치가 발견되면 값을 NULL로 설정해요. null 문자열이 비어 있는 기본 경우, 이는 인용된 빈 문자열을 NULL로 변환해요. *를 지정하면 옵션이 모든 컬럼에 적용돼요. 이 옵션은 COPY FROM에서만, 그리고 CSV 형식을 사용할 때만 허용돼요.
ON_ERROR
컬럼의 입력 값을 데이터 타입으로 변환하는 중 오류를 만났을 때 어떻게 동작할지 지정해요. error_action 값 stop은 명령을 실패시키고, ignore는 입력 행을 버리고 다음으로 계속한다는 뜻이에요. 기본값은 stop이에요.
ignore 옵션은 FORMAT이 text 또는 csv일 때 COPY FROM에만 적용 가능해요.
최소한 한 행이 버려지면 COPY FROM 끝에 무시된 행 수를 담은 NOTICE 메시지가 발행돼요. LOG_VERBOSITY 옵션이 verbose로 설정되면 버려진 각 행에 대해 입력 파일의 줄과 입력 변환이 실패한 컬럼 이름을 담은 NOTICE 메시지가 발행돼요. silent로 설정되면 무시된 행에 대한 메시지는 발행되지 않아요.
REJECT_LIMIT
ON_ERROR가 ignore로 설정되었을 때 컬럼의 입력 값을 데이터 타입으로 변환하는 동안 허용되는 최대 오류 수를 지정해요. 입력이 지정된 값보다 더 많은 오류를 일으키면 COPY 명령은 ON_ERROR가 ignore로 설정되어 있어도 실패해요. 이 절은 ON_ERROR=ignore와 함께 사용되어야 하고 *maxerror*은 양수 bigint여야 해요. 지정하지 않으면 ON_ERROR=ignore는 무제한 오류를 허용하며, 이는 COPY가 모든 잘못된 데이터를 건너뛴다는 뜻이에요.
ENCODING
파일이 *encoding_name*으로 인코딩되어 있음을 지정해요. 이 옵션을 생략하면 현재 클라이언트 인코딩이 사용돼요. 자세한 내용은 아래의 Notes를 참고해요.
LOG_VERBOSITY
COPY 명령이 발행하는 메시지의 양을 지정해요. default, verbose, silent예요. verbose를 지정하면 처리 중 추가 메시지가 발행돼요. silent는 verbose와 기본 메시지를 모두 억제해요.
이는 현재 ON_ERROR 옵션이 ignore로 설정된 COPY FROM 명령에서 사용돼요.
WHERE
선택적인 WHERE 절은 일반적으로 다음과 같은 형태를 가져요:
WHERE condition
여기서 *condition*은 boolean 타입 결과로 평가되는 어떤 표현식이든 돼요. 이 조건을 만족하지 않는 행은 테이블에 삽입되지 않아요. 행은 실제 행 값이 변수 참조를 대체했을 때 true를 반환하면 조건을 만족해요.
현재 서브쿼리와 생성 컬럼은 WHERE 표현식에서 허용되지 않으며, 평가는 COPY 자체가 만든 변경 사항을 보지 못해요 (이는 표현식이 VOLATILE 함수 호출을 포함할 때 중요해요).
Outputs
성공적으로 완료되면 COPY 명령은 다음 형태의 명령 태그를 반환해요:
COPY count
*count*는 복사된 행의 수예요.
참고 (Note)
psql은 명령이
COPY ... TO STDOUT이거나 동등한 psql 메타 명령인\copy ... to stdout이 아닌 경우에만 이 명령 태그를 출력해요. 이는 명령 태그를 방금 출력된 데이터와 혼동하는 것을 방지하기 위함이에요.
Notes
COPY TO는 일반 테이블과 채워진 구체화된 뷰에 사용할 수 있어요. 예를 들어 COPY *table* TO는 SELECT * FROM ONLY *table*과 같은 행을 복사해요. 하지만 파티션 테이블, 상속 자식 테이블, 뷰 같은 다른 관계 유형은 직접 지원하지 않아요. 그런 관계의 모든 행을 복사하려면 COPY (SELECT * FROM *table*) TO를 사용해요.
COPY FROM은 일반, 외부, 파티션 테이블 또는 INSTEAD OF INSERT 트리거가 있는 뷰에 사용할 수 있어요.
COPY TO가 값을 읽는 테이블에는 select 권한이, COPY FROM이 값을 삽입하는 테이블에는 insert 권한이 있어야 해요. 명령에 나열된 컬럼(들)에 대한 컬럼 권한이 있으면 충분해요.
테이블에 행 수준 보안(row-level security)이 활성화되면 관련 SELECT 정책이 COPY *table* TO 문에도 적용돼요. 현재 COPY FROM은 행 수준 보안이 있는 테이블에서 지원되지 않아요. 대신 동등한 INSERT 문을 사용해요.
COPY 명령에 이름이 지정된 파일은 클라이언트 애플리케이션이 아니라 서버가 직접 읽거나 씁니다. 따라서 그들은 클라이언트가 아니라 데이터베이스 서버 머신에 있거나 접근 가능해야 해요. 클라이언트가 아니라 PostgreSQL 사용자(서버가 실행되는 사용자 ID)가 접근할 수 있고 읽거나 쓸 수 있어야 해요. 마찬가지로 PROGRAM으로 지정된 명령은 클라이언트 애플리케이션이 아니라 서버에 의해 직접 실행되며, PostgreSQL 사용자가 실행할 수 있어야 해요. 파일이나 명령의 이름을 지정하는 COPY는 서버가 접근할 권한이 있는 파일을 읽거나 쓰거나 프로그램을 실행할 수 있게 하므로, 데이터베이스 슈퍼유저 또는 pg_read_server_files, pg_write_server_files, pg_execute_server_program 역할 중 하나를 부여받은 사용자만 허용돼요.
COPY를 psql 명령 \copy와 혼동하지 마세요. \copy는 COPY FROM STDIN 또는 COPY TO STDOUT을 호출한 다음 psql 클라이언트가 접근할 수 있는 파일에 데이터를 가져오거나 저장해요. 따라서 \copy를 사용하면 파일 접근성과 접근 권한은 서버가 아니라 클라이언트에 달려요.
COPY에서 사용되는 파일 이름은 항상 절대 경로로 지정하는 것이 좋아요. 이는 COPY TO의 경우 서버가 강제하지만, COPY FROM의 경우 상대 경로로 지정된 파일에서 읽을 수 있는 옵션이 있어요. 경로는 클라이언트의 작업 디렉토리가 아니라 서버 프로세스의 작업 디렉토리(보통 클러스터의 데이터 디렉토리)에 대해 상대적으로 해석돼요.
PROGRAM으로 명령을 실행하는 것은 SELinux 같은 운영체제의 접근 제어 메커니즘에 의해 제한될 수 있어요.
COPY FROM은 대상 테이블의 모든 트리거와 체크 제약을 호출해요. 하지만 규칙(rule)은 호출하지 않아요.
신원(identity) 컬럼의 경우 COPY FROM 명령은 항상 입력 데이터에서 제공된 컬럼 값을 작성해요. 마치 INSERT 옵션 OVERRIDING SYSTEM VALUE처럼요.
COPY 입력과 출력은 DateStyle의 영향을 받아요. 기본값이 아닌 DateStyle 설정을 사용할 수 있는 다른 PostgreSQL 설치로의 이식성을 보장하려면 COPY TO를 사용하기 전에 DateStyle을 ISO로 설정해야 해요. 또한 IntervalStyle이 sql_standard로 설정된 상태에서 데이터를 덤프하는 것은 피하는 것이 좋은데, IntervalStyle에 대한 다른 설정을 가진 서버가 음수 간격 값을 잘못 해석할 수 있기 때문이에요.
입력 데이터는 ENCODING 옵션이나 현재 클라이언트 인코딩에 따라 해석되고, 출력 데이터는 ENCODING 또는 현재 클라이언트 인코딩으로 인코딩돼요. 데이터가 클라이언트를 통과하지 않고 서버가 파일에서 직접 읽거나 파일에 직접 쓰더라도 마찬가지예요.
COPY FROM 명령은 진행됨에 따라 입력 행을 물리적으로 테이블에 삽입해요. 명령이 실패하면 이 행들은 삭제된 상태로 남으며, 보이지는 않지만 여전히 디스크 공간을 차지해요. 대규모 복사 작업 도중에 실패가 발생했다면 상당한 양의 디스크 공간이 낭비될 수 있어요. 낭비된 공간을 회수하려면 VACUUM을 사용해야 해요.
FORCE_NULL과 FORCE_NOT_NULL은 같은 컬럼에 동시에 사용할 수 있어요. 이는 인용된 null 문자열을 null 값으로, 인용되지 않은 null 문자열을 빈 문자열로 변환하는 결과를 만들어요.
File Formats
Text Format
text 형식을 사용할 때 읽거나 쓰는 데이터는 테이블 행당 한 줄이 있는 텍스트 파일이에요. 행의 컬럼은 구분 문자로 분리돼요. 컬럼 값 자체는 각 속성의 데이터 타입의 출력 함수가 생성하거나 입력 함수가 허용하는 문자열이에요. null인 컬럼 대신 지정된 null 문자열이 사용돼요. COPY FROM은 입력 파일의 어떤 줄에 예상보다 많거나 적은 컬럼이 있으면 오류를 발생시켜요.
데이터의 끝은 백슬래시-마침표(\.)만 있는 줄로 나타낼 수 있어요. 파일에서 읽을 때는 파일의 끝이 완벽하게 그 역할을 하므로 끝-데이터 표시는 필요하지 않아요. 그 문맥에서 이 조항은 하위 호환성을 위해서만 존재해요. 하지만 psql은 COPY FROM STDIN 작업(즉 SQL 스크립트에서 인라인 COPY 데이터를 읽는 것)을 종료하는 데 \.를 사용해요. 그 문맥에서는 스크립트의 끝보다 앞서 작업을 끝낼 수 있도록 그 규칙이 필요해요.
백슬래시 문자(\)는 COPY 데이터에서 행 또는 컬럼 구분자로 잘못 취해질 수 있는 데이터 문자를 인용하는 데 사용될 수 있어요. 특히 다음 문자들은 컬럼 값의 일부로 나타나면 앞에 백슬래시가 와야 합니다: 백슬래시 자체, 개행, 캐리지 리턴, 현재 구분 문자.
지정된 null 문자열은 COPY TO가 백슬래시를 추가하지 않고 보내요. 반대로 COPY FROM은 백슬래시를 제거하기 전에 입력을 null 문자열과 대조해요. 따라서 \N 같은 null 문자열은 실제 데이터 값 \N(그 값은 \\N으로 표현됨)과 혼동될 수 없어요.
COPY FROM이 인식하는 특별한 백슬래시 시퀀스는 다음과 같아요:
| Sequence | Represents |
|---|---|
| \b | Backspace (ASCII 8) |
| \f | Form feed (ASCII 12) |
| \n | Newline (ASCII 10) |
| \r | Carriage return (ASCII 13) |
| \t | Tab (ASCII 9) |
| \v | Vertical tab (ASCII 11) |
| \digits | Backslash followed by one to three octal digits specifies the byte with that numeric code |
| \xdigits | Backslash x followed by one or two hex digits specifies the byte with that numeric code |
현재 COPY TO는 8진수 또는 16진수 자릿수 백슬래시 시퀀스를 절대 출력하지 않지만, 위에 나열된 다른 시퀀스는 그 제어 문자들에 대해 사용해요.
위 표에 언급되지 않은 다른 백슬래시 문자가 있으면 자기 자신을 나타내는 것으로 취해져요. 하지만 백슬래시를 불필요하게 추가하지 않도록 주의하세요. 끝-데이터 표시(\.)나 null 문자열(기본 \N)과 일치하는 문자열을 실수로 만들 수 있기 때문이에요. 이 문자열들은 다른 백슬래시 처리가 수행되기 전에 인식돼요.
COPY 데이터를 생성하는 애플리케이션이 데이터 개행과 캐리지 리턴을 각각 \n과 \r 시퀀스로 변환하는 것이 강력히 권장돼요. 현재 데이터 캐리지 리턴을 백슬래시와 캐리지 리턴으로, 데이터 개행을 백슬래시와 개행으로 나타내는 것이 가능해요. 하지만 이러한 표현은 향후 릴리스에서 허용되지 않을 수 있어요. 또한 COPY 파일이 다른 머신(예: Unix에서 Windows로 또는 그 반대로)으로 전송되면 손상에 매우 취약해요.
모든 백슬래시 시퀀스는 인코딩 변환 후에 해석돼요. 8진수 및 16진수 자릿수 백슬래시 시퀀스로 지정된 바이트는 데이터베이스 인코딩에서 유효한 문자를 형성해야 해요.
COPY TO는 각 행을 Unix 스타일 개행("\n")으로 종료해요. Microsoft Windows에서 실행되는 서버는 대신 캐리지 리턴/개행("\r\n")을 출력하지만, 서버 파일로의 COPY에만 해당돼요. 플랫폼 간 일관성을 위해 COPY TO STDOUT은 서버 플랫폼에 관계없이 항상 "\n"을 보내요. COPY FROM은 개행, 캐리지 리턴, 또는 캐리지 리턴/개행으로 끝나는 줄을 처리할 수 있어요. 데이터로 의도된 백슬래시가 없는 개행이나 캐리지 리턴 때문에 오류가 발생할 위험을 줄이기 위해, COPY FROM은 입력의 줄 끝이 모두 같지 않으면 불평해요.
CSV Format
이 형식 옵션은 스프레드시트 같은 많은 다른 프로그램이 사용하는 쉼표로 구분된 값(CSV) 파일 형식을 가져오고 내보내는 데 사용돼요. PostgreSQL의 표준 text 형식이 사용하는 이스케이프 규칙 대신, 일반적인 CSV 이스케이프 메커니즘을 생성하고 인식해요.
각 레코드의 값은 DELIMITER 문자로 분리돼요. 값이 구분 문자, QUOTE 문자, NULL 문자열, 캐리지 리턴, 개행 문자를 포함하면, 전체 값이 QUOTE 문자로 앞뒤가 붙고, 값 안의 QUOTE 문자 또는 ESCAPE 문자의 모든 출현 앞에는 이스케이프 문자가 옵니다. 또한 특정 컬럼에서 비-NULL 값을 출력할 때 인용을 강제하려면 FORCE_QUOTE를 사용할 수 있어요.
CSV 형식에는 NULL 값을 빈 문자열과 구분하는 표준 방법이 없어요. PostgreSQL의 COPY는 인용을 통해 이를 처리해요. NULL은 NULL 매개변수 문자열로 출력되고 인용되지 않는 반면, NULL 매개변수 문자열과 일치하는 비-NULL 값은 인용돼요. 예를 들어 기본 설정에서 NULL은 인용되지 않은 빈 문자열로 작성되고, 빈 문자열 데이터 값은 큰따옴표("")로 작성돼요. 값을 읽는 것은 유사한 규칙을 따릅니다. 특정 컬럼에 대한 NULL 입력 비교를 방지하려면 FORCE_NOT_NULL을 사용할 수 있어요. 또한 FORCE_NULL을 사용해 인용된 null 문자열 데이터 값을 NULL로 변환할 수 있어요.
백슬래시는 CSV 형식에서 특수 문자가 아니므로, text 모드에서 사용되는 끝-데이터 표시(\.)는 CSV 데이터를 읽을 때 보통 특수하게 취급되지 않아요. 예외는 psql이 \.만 있는 줄에서 COPY FROM STDIN 작업(즉 SQL 스크립트에서 인라인 COPY 데이터를 읽는 것)을 종료한다는 것인데, text든 CSV 모드든 마찬가지예요.
참고 (Note)
v18 이전의 PostgreSQL 버전은 별도 파일에서 읽을 때조차 인용되지 않은
\.를 항상 끝-데이터 표시로 인식했어요. 이전 버전과의 호환성을 위해COPY TO는 더 이상 필요하지 않더라도 줄에 단독으로 있을 때\.를 인용해요.
참고 (Note)
CSV형식에서는 모든 문자가 의미가 있어요. 공백으로 둘러싸인 인용 값이나DELIMITER이외의 문자는 그 문자들을 포함해요. 이는CSV줄을 고정 너비로 공백으로 채우는 시스템에서 데이터를 가져오면 오류를 일으킬 수 있어요. 그런 상황이 발생하면 데이터를 PostgreSQL로 가져오기 전에CSV파일을 전처리해 끝 공백을 제거해야 할 수 있어요.
참고 (Note)
CSV형식은 캐리지 리턴과 개행이 포함된 인용 값을 가진CSV파일을 인식하고 생성해요. 따라서 이 파일들은 text 형식 파일처럼 테이블 행당 엄격히 한 줄이 아니에요.
참고 (Note)
많은 프로그램이 이상하고 때로는 변태적인
CSV파일을 만들므로, 파일 형식은 표준보다 관례에 가까워요. 따라서 이 메커니즘으로 가져올 수 없는 파일을 만날 수도 있고,COPY가 다른 프로그램이 처리할 수 없는 파일을 만들 수도 있어요.
Binary Format
binary 형식 옵션은 모든 데이터를 텍스트가 아닌 이진 형식으로 저장/읽도록 해요. text 및 CSV 형식보다 다소 빠르지만, 이진 형식 파일은 머신 아키텍처와 PostgreSQL 버전 간 이식성이 떨어져요. 또한 이진 형식은 데이터 타입에 매우 특화되어 있어요. 예를 들어 smallint 컬럼에서 이진 데이터를 출력해 integer 컬럼으로 읽는 것은 text 형식에서는 잘 작동해도 작동하지 않을 거예요.
binary 파일 형식은 파일 헤더, 행 데이터를 포함하는 0개 이상의 튜플, 파일 트레일러로 구성돼요. 헤더와 데이터는 네트워크 바이트 순서입니다.
참고 (Note)
7.4 이전의 PostgreSQL 릴리스는 다른 이진 파일 형식을 사용했어요.
File Header
파일 헤더는 15바이트의 고정 필드 뒤에 가변 길이 헤더 확장 영역으로 구성돼요. 고정 필드는:
Signature
11바이트 시퀀스 PGCOPY\n\377\r\n\0 — 널 바이트가 시그니처의 필수 부분이라는 점을 참고하세요. (시그니처는 비-8비트-클린 전송에 의해 손상된 파일을 쉽게 식별할 수 있도록 설계됐어요. 이 시그니처는 줄 끝 변환 필터, 떨어진 널 바이트, 떨어진 상위 비트, 또는 패리티 변경에 의해 변경됩니다.)
Flags field
파일 형식의 중요한 측면을 나타내는 32비트 정수 비트 마스크예요. 비트는 0 (LSB)부터 31 (MSB)까지 번호가 매겨져요. 이 필드는 파일 형식에 사용되는 모든 정수 필드처럼 네트워크 바이트 순서(가장 중요한 바이트 먼저)로 저장된다는 점을 참고하세요. 비트 16–31은 중요한 파일 형식 문제를 나타내도록 예약되어 있으며, 읽는 쪽은 이 범위에서 예상치 못한 비트가 설정된 것을 발견하면 중단해야 해요. 비트 0–15는 하위 호환 형식 문제를 신호하도록 예약되어 있으며, 읽는 쪽은 이 범위에서 설정된 예상치 못한 비트를 그냥 무시해야 해요. 현재는 하나의 플래그 비트만 정의되어 있고 나머지는 0이어야 해요:
Bit 16
1이면 데이터에 OID가 포함되고, 0이면 포함되지 않아요. OID 시스템 컬럼은 더 이상 PostgreSQL에서 지원되지 않지만, 형식은 여전히 표시자를 포함해요.
Header extension area length
32비트 정수로, 자기 자신을 포함하지 않는 나머지 헤더의 길이(바이트)예요. 현재는 0이고, 첫 튜플이 바로 이어집니다. 형식의 향후 변경은 헤더에 추가 데이터가 존재하도록 허용할 수 있어요. 독자는 처리 방법을 모르는 헤더 확장 데이터를 조용히 건너뛰어야 해요.
헤더 확장 영역은 자기 식별 청크(self-identifying chunk)들의 시퀀스를 포함하도록 구상됐어요. 플래그 필드는 확장 영역에 무엇이 있는지 독자에게 말하도록 의도된 것이 아니에요. 헤더 확장 내용의 구체적 설계는 이후 릴리스로 남겨져 있어요.
이 설계는 하위 호환 헤더 추가(헤더 확장 청크 추가 또는 낮은 순서 플래그 비트 설정)와 비하위 호환 변경(높은 순서 플래그 비트를 설정해 그런 변경을 신호하고 필요하면 확장 영역에 지원 데이터 추가)을 모두 허용해요.
Tuples
각 튜플은 튜플의 필드 수의 16비트 정수 카운트로 시작해요. (현재 테이블의 모든 튜플은 같은 카운트를 갖지만, 항상 그런 것은 아닐 수 있어요.) 그런 다음 튜플의 각 필드에 대해 반복되는 32비트 길이 단어와 그만큼의 필드 데이터 바이트가 있습니다. (길이 단어는 자기 자신을 포함하지 않으며 0일 수 있어요.) 특수한 경우로 -1은 NULL 필드 값을 나타내요. NULL 경우 값 바이트는 뒤따르지 않아요.
필드 사이에 정렬 패딩이나 다른 추가 데이터는 없어요.
현재 이진 형식 파일의 모든 데이터 값은 이진 형식(형식 코드 1)이라고 가정돼요. 향후 확장이 컬럼별 형식 코드를 지정할 수 있는 헤더 필드를 추가할 수 있을 것으로 예상돼요.
실제 튜플 데이터에 대한 적절한 이진 형식을 결정하려면 PostgreSQL 소스를 참고해야 하며, 특히 각 컬럼의 데이터 타입에 대한 *send 및 *recv 함수를 봐야 해요 (이 함수들은 보통 소스 배포판의 src/backend/utils/adt/ 디렉토리에 있어요).
파일에 OID가 포함되면 OID 필드는 필드 카운트 단어 바로 뒤에 옵니다. 그것은 필드 카운트에 포함되지 않는다는 점을 제외하고는 일반 필드예요. oid 시스템 컬럼은 현재 PostgreSQL 버전에서 지원되지 않는다는 점을 참고하세요.
File Trailer
파일 트레일러는 -1을 포함하는 16비트 정수 단어로 구성돼요. 이는 튜플의 필드 카운트 단어와 쉽게 구별돼요.
읽는 쪽은 필드 카운트 단어가 -1도 아니고 예상 컬럼 수도 아니면 오류를 보고해야 해요. 이는 데이터와의 동기화가 어긋나는 것을 방지하기 위한 추가 검사를 제공해요.
Examples
다음 예시는 세로 막대(|)를 필드 구분자로 사용해 테이블을 클라이언트로 복사해요:
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';
압축 파일로 복사하려면 출력을 외부 압축 프로그램에 파이프할 수 있어요:
COPY country TO PROGRAM 'gzip > /usr1/proj/bray/sql/country_data.gz';
STDIN에서 테이블로 복사하기에 적합한 데이터 샘플:
AF AFGHANISTAN
AL ALBANIA
DZ ALGERIA
ZM ZAMBIA
ZW ZIMBABWE
각 줄의 공백은 실제로는 탭 문자라는 점을 참고하세요.
다음은 같은 데이터를 이진 형식으로 출력한 것입니다. 데이터는 Unix 유틸리티 od -c로 필터링한 후 보여집니다. 테이블은 세 개의 컬럼이 있고, 첫 번째는 char(2), 두 번째는 text, 세 번째는 integer 타입이에요. 모든 행은 세 번째 컬럼에 null 값이 있어요.
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 ]
[ 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 ]
[ DELIMITER [ AS ] 'delimiter_character' ]
[ NULL [ AS ] 'null_string' ]
[ CSV [ HEADER ]
[ QUOTE [ AS ] 'quote_character' ]
[ ESCAPE [ AS ] 'escape_character' ]
[ FORCE QUOTE { column_name [, ...] | * } ] ] ]
이 문법에서 BINARY와 CSV는 FORMAT 옵션의 인자가 아니라 독립적인 키워드로 취급된다는 점을 참고하세요.
PostgreSQL 7.3 이전에 사용되던 문법이며 여전히 지원되는 형태:
COPY [ BINARY ] table_name
FROM { 'filename' | STDIN }
[ [USING] DELIMITERS 'delimiter_character' ]
[ WITH NULL AS 'null_string' ]
COPY [ BINARY ] table_name
TO { 'filename' | STDOUT }
[ [USING] DELIMITERS 'delimiter_character' ]
[ WITH NULL AS 'null_string' ]