CREATE FOREIGN TABLE — 새 외부 테이블 정의하기

CREATE FOREIGN TABLE — 새 외부 테이블 정의하기

CREATE FOREIGN TABLE 명령은 현재 데이터베이스에 새 외부 테이블(foreign table)을 생성하는 명령이에요. 외부 서버를 통해 원격 데이터에 접근하는 테이블 구조를 정의하며, 외부 데이터 래퍼(FDW)와 함께 사용돼요.

출처: PostgreSQL 문서

본문

Synopsis

CREATE FOREIGN TABLE [ IF NOT EXISTS ] table_name ( [
  { column_name data_type [ OPTIONS ( option 'value' [, ... ] ) ] [ COLLATE collation ] [ column_constraint [ ... ] ]
    | table_constraint
    | LIKE source_table [ like_option ... ] }
    [, ... ]
] )
[ INHERITS ( parent_table [, ... ] ) ]
  SERVER server_name
[ OPTIONS ( option 'value' [, ... ] ) ]

CREATE FOREIGN TABLE [ IF NOT EXISTS ] table_name
  PARTITION OF parent_table [ (
  { column_name [ WITH OPTIONS ] [ column_constraint [ ... ] ]
    | table_constraint }
    [, ... ]
) ]
{ FOR VALUES partition_bound_spec | DEFAULT }
  SERVER server_name
[ OPTIONS ( option 'value' [, ... ] ) ]

where column_constraint is:

[ CONSTRAINT constraint_name ]
{ NOT NULL [ NO INHERIT ] |
  NULL |
  CHECK ( expression ) [ NO INHERIT ] |
  DEFAULT default_expr |
  GENERATED ALWAYS AS ( generation_expr ) [ STORED | VIRTUAL ] }
[ ENFORCED | NOT ENFORCED ]

and table_constraint is:

[ CONSTRAINT constraint_name ]
{  NOT NULL column_name [ NO INHERIT ] |
   CHECK ( expression ) [ NO INHERIT ] }
[ ENFORCED | NOT ENFORCED ]

and like_option is:

{ INCLUDING | EXCLUDING } { COMMENTS | CONSTRAINTS | DEFAULTS | GENERATED | STATISTICS | ALL }

and partition_bound_spec is:

IN ( partition_bound_expr [, ...] ) |
FROM ( { partition_bound_expr | MINVALUE | MAXVALUE } [, ...] )
  TO ( { partition_bound_expr | MINVALUE | MAXVALUE } [, ...] ) |
WITH ( MODULUS numeric_literal, REMAINDER numeric_literal )

Description

CREATE FOREIGN TABLE은 현재 데이터베이스에 새 외부 테이블을 생성해요. 테이블은 명령을 실행한 사용자가 소유해요.

스키마 이름이 주어지면(예: CREATE FOREIGN TABLE myschema.mytable ...) 테이블은 지정된 스키마에 생성돼요. 그렇지 않으면 현재 스키마에 생성돼요. 외부 테이블의 이름은 같은 스키마의 다른 모든 관계(테이블, 시퀀스, 인덱스, 뷰, 구체화된 뷰, 외부 테이블)의 이름과 구별되어야 해요.

CREATE FOREIGN TABLE은 또한 외부 테이블의 한 행에 해당하는 복합 타입을 나타내는 데이터 타입을 자동으로 생성해요. 따라서 외부 테이블은 같은 스키마의 기존 데이터 타입과 같은 이름을 가질 수 없어요.

PARTITION OF 절이 지정되면 테이블은 지정된 경계를 가진 parent_table의 파티션으로 생성돼요.

외부 테이블을 만들려면 외부 서버에 대한 USAGE 권한과, 테이블에서 사용되는 모든 컬럼 타입에 대한 USAGE 권한이 있어야 해요.

Parameters

IF NOT EXISTS

같은 이름의 관계가 이미 존재하면 오류를 던지지 않아요. 이 경우 공지가 발행돼요. 참고로 기존 관계가 생성됐을 관계와 어떤 식으로든 같다는 보장은 없어요.

table_name

생성할 테이블의 이름이에요 (선택적으로 스키마 한정).

column_name

새 테이블에 생성할 컬럼의 이름이에요.

data_type

컬럼의 데이터 타입이에요. 배열 지정자를 포함할 수 있어요. PostgreSQL이 지원하는 데이터 타입에 대한 더 자세한 정보는 8장을 참고해요.

COLLATE collation

COLLATE 절은 컬럼에 콜레이션을 할당해요 (콜레이션 가능한 데이터 타입이어야 해요). 지정하지 않으면 컬럼 데이터 타입의 기본 콜레이션이 사용돼요.

INHERITS ( parent_table [, ... ] )

선택적인 INHERITS 절은 새 외부 테이블이 모든 컬럼을 자동으로 상속하는 테이블 목록을 지정해요. 부모 테이블은 일반 테이블이거나 외부 테이블일 수 있어요. 자세한 내용은 CREATE TABLE의 유사한 형태를 참고해요.

PARTITION OF parent_table { FOR VALUES partition_bound_spec | DEFAULT }

이 형태는 지정된 파티션 경계 값을 가진 외부 테이블을 주어진 부모 테이블의 파티션으로 만들 때 사용할 수 있어요. 자세한 내용은 CREATE TABLE의 유사한 형태를 참고해요. 부모 테이블에 UNIQUE 인덱스가 있으면 외부 테이블을 부모 테이블의 파티션으로 만드는 것은 현재 허용되지 않는다는 점을 참고하세요. (ALTER TABLE ATTACH PARTITION도 참고하세요.)

LIKE source_table [ like_option ... ]

LIKE 절은 새 테이블이 모든 컬럼 이름, 데이터 타입, not-null 제약을 자동으로 복사하는 테이블을 지정해요.

INHERITS와 달리, 생성이 완료되면 새 테이블과 원래 테이블은 완전히 분리돼요. 원래 테이블의 변경은 새 테이블에 적용되지 않으며, 원래 테이블 스캔에 새 테이블의 데이터를 포함시키는 것도 불가능해요.

또한 INHERITS와 달리 LIKE가 복사한 컬럼과 제약은 같은 이름의 컬럼과 제약과 병합되지 않아요. 같은 이름이 명시적이거나 다른 LIKE 절에 지정되면 오류가 발생해요.

선택적인 like_option 절은 원래 테이블의 어떤 추가 속성을 복사할지 지정해요. INCLUDING을 지정하면 속성을 복사하고, EXCLUDING을 지정하면 속성을 생략해요. 기본값은 EXCLUDING이에요. 같은 종류의 객체에 대해 여러 사양이 만들어지면 마지막 것이 사용돼요. 사용 가능한 옵션은:

INCLUDING COMMENTS

복사된 컬럼, 제약, 확장 통계에 대한 주석이 복사돼요. 기본 동작은 주석을 제외해서, 새 테이블의 해당 객체들이 주석이 없도록 하는 거예요.

INCLUDING CONSTRAINTS

CHECK 제약이 복사돼요. 컬럼 제약과 테이블 제약은 구별되지 않아요. not-null 제약은 항상 새 테이블로 복사돼요.

INCLUDING DEFAULTS

복사된 컬럼 정의에 대한 기본 표현식이 복사돼요. 그렇지 않으면 기본 표현식은 복사되지 않아서 새 테이블의 복사된 컬럼이 null 기본값을 갖게 돼요. nextval 같은 데이터베이스 수정 함수를 호출하는 기본값을 복사하면 원래 테이블과 새 테이블 사이에 기능적 연결이 생길 수 있다는 점을 참고하세요.

INCLUDING GENERATED

복사된 컬럼 정의의 생성 표현식(generation expression)이 복사돼요. 기본적으로 새 컬럼은 일반 기본 컬럼이 돼요.

INCLUDING STATISTICS

확장 통계가 새 테이블로 복사돼요.

INCLUDING ALL

INCLUDING ALL은 사용 가능한 모든 개별 옵션을 선택하는 약식 형태예요. (전부 말고 특정 옵션 몇 개만 빼고 선택하려면 INCLUDING ALL 뒤에 개별 EXCLUDING 절을 쓰면 유용할 수 있어요.)

CONSTRAINT constraint_name

컬럼 또는 테이블 제약에 대한 선택적인 이름이에요. 제약이 위반되면 제약 이름이 오류 메시지에 나타나므로, col must be positive 같은 제약 이름이 클라이언트 애플리케이션에 유용한 제약 정보를 전달하는 데 사용될 수 있어요. (공백을 포함하는 제약 이름을 지정하려면 큰따옴표가 필요해요.) 제약 이름을 지정하지 않으면 시스템이 이름을 생성해요.

NOT NULL [ NO INHERIT ]

컬럼은 null 값을 포함할 수 없어요.

NO INHERIT로 표시된 제약은 자식 테이블로 전파되지 않아요.

NULL

컬럼은 null 값을 포함할 수 있어요. 이것이 기본값이에요.

이 절은 비표준 SQL 데이터베이스와의 호환성을 위해서만 제공돼요. 새 애플리케이션에서 그 사용은 권장되지 않아요.

CHECK ( expression ) [ NO INHERIT ]

CHECK 절은 외부 테이블의 각 행이 만족해야 하는 Boolean 결과를 만드는 표현식을 지정해요. 즉 그 표현식은 외부 테이블의 모든 행에 대해 TRUE 또는 UNKNOWN을 만들어야 하고, 결코 FALSE는 아니어야 해요. 컬럼 제약으로 지정된 체크 제약은 그 컬럼의 값만 참조해야 하고, 테이블 제약에 나타나는 표현식은 여러 컬럼을 참조할 수 있어요.

현재 CHECK 표현식은 서브쿼리를 포함할 수 없고 현재 행의 컬럼 외의 변수를 참조할 수 없어요. 시스템 컬럼 tableoid는 참조할 수 있지만, 다른 시스템 컬럼은 참조할 수 없어요.

NO INHERIT로 표시된 제약은 자식 테이블로 전파되지 않아요.

DEFAULT default_expr

DEFAULT 절은 그 컬럼 정의가 나타나는 컬럼에 대한 기본 데이터 값을 할당해요. 그 값은 변수가 없는 어떤 표현식이든 될 수 있어요 (서브쿼리와 현재 테이블의 다른 컬럼에 대한 교차 참조는 허용되지 않아요). 기본 표현식의 데이터 타입은 컬럼의 데이터 타입과 일치해야 해요.

기본 표현식은 컬럼에 값을 지정하지 않는 어떤 삽입 연산에서도 사용돼요. 컬럼에 대한 기본값이 없으면 기본값은 null이에요.

GENERATED ALWAYS AS ( generation_expr ) [ STORED | VIRTUAL ]

이 절은 컬럼을 생성 컬럼(generated column)으로 만들어요. 이 컬럼에는 쓸 수 없고, 읽을 때 지정된 표현식의 결과가 반환돼요.

VIRTUAL을 지정하면 컬럼은 읽을 때 계산돼요. (외부 데이터 래퍼는 새 행에서 이를 null 값으로 보고, null 값으로 저장하거나 완전히 무시할 수 있어요.) STORED를 지정하면 컬럼은 쓰기 시 계산돼요. (계산된 값은 저장을 위해 외부 데이터 래퍼에 제시되고, 읽기 시 반환되어야 해요.) 기본값은 VIRTUAL이에요.

생성 표현식은 테이블의 다른 컬럼을 참조할 수 있지만, 다른 생성 컬럼은 참조할 수 없어요. 사용되는 모든 함수와 연산자는 불변(immutable)이어야 해요. 다른 테이블에 대한 참조는 허용되지 않아요.

server_name

외부 테이블에 사용할 기존 외부 서버의 이름이에요. 서버 정의에 대한 자세한 내용은 CREATE SERVER를 참고해요.

OPTIONS ( option 'value' [, ...] )

새 외부 테이블 또는 그 컬럼 중 하나와 연결될 옵션들이에요. 허용되는 옵션 이름과 값은 각 외부 데이터 래퍼마다 다르며, 외부 데이터 래퍼의 검증자 함수를 사용해 검증돼요. 중복된 옵션 이름은 허용되지 않아요 (테이블 옵션과 컬럼 옵션이 같은 이름을 가진 것은 괜찮아요).

Notes

외부 테이블의 제약(CHECK 또는 NOT NULL 절 같은)은 핵심 PostgreSQL 시스템이 적용하지 않으며, 대부분의 외부 데이터 래퍼도 적용하려 하지 않아요. 즉 그 제약은 단순히 참이라고 가정돼요. 그런 적용은 외부 테이블을 통해 삽입·갱신된 행에만 적용되고 원격 서버에서 직접 수정된 행 같은 다른 방법으로 수정된 행에는 적용되지 않으므로, 그런 적용에는 별 의미가 없어요. 대신 외부 테이블에 붙은 제약은 원격 서버가 적용하고 있는 제약을 나타내야 해요.

일부 특수 목적 외부 데이터 래퍼는 그들이 접근하는 데이터의 유일한 접근 메커니즘일 수 있으며, 그 경우 외부 데이터 래퍼 자체가 제약 적용을 수행하는 것이 적절할 수 있어요. 하지만 문서에 그렇게 명시하지 않는 한 래퍼가 그런 일을 한다고 가정해서는 안 돼요.

PostgreSQL이 외부 테이블의 제약을 적용하려 하지는 않지만, 쿼리 최적화 목적을 위해 그것들이 올바르다고 가정해요. 외부 테이블에 선언된 제약을 만족하지 않는 행이 보이면, 테이블에 대한 쿼리가 오류나 잘못된 답을 만들 수 있어요. 제약 정의가 실제와 일치하는지 확인하는 것은 사용자의 책임이에요.

주의 (Caution)

외부 테이블이 파티션 테이블의 파티션으로 사용될 때, 그 내용이 파티션 규칙을 만족해야 한다는 암시적 제약이 있어요. 다시 말하지만 그것이 실제로 참인지 확인하는 것은 사용자의 책임이며, 원격 서버에 일치하는 제약을 설치하는 것이 가장 좋은 방법이에요.

외부 테이블 파티션을 포함하는 파티션 테이블 안에서, 파티션 키 값을 변경하는 UPDATE는 외부 데이터 래퍼가 튜플 라우팅을 지원한다면 행을 로컬 파티션에서 외부 테이블 파티션으로 이동시킬 수 있어요. 하지만 현재 외부 테이블 파티션에서 다른 파티션으로 행을 이동시키는 것은 불가능해요. 그런 일을 요구하는 UPDATE는, 원격 서버가 제대로 적용하고 있다고 가정하면, 파티셔닝 제약 때문에 실패해요.

유사한 고려 사항이 생성 컬럼에도 적용돼요. 저장된 생성 컬럼은 로컬 PostgreSQL 서버에서 삽입 또는 갱신 시 계산되어 외부 데이터 래퍼에 전달되어 외부 데이터 저장소에 기록되지만, 외부 테이블 쿼리가 생성 표현식과 일치하는 저장된 생성 컬럼 값을 반환한다는 것은 강제되지 않아요. 이 역시 잘못된 쿼리 결과를 초래할 수 있어요.

Examples

서버 film_server를 통해 접근할 외부 테이블 films를 생성하기:

CREATE FOREIGN TABLE films (
    code        char(5) NOT NULL,
    title       varchar(40) NOT NULL,
    did         integer NOT NULL,
    date_prod   date,
    kind        varchar(10),
    len         interval hour to minute
)
SERVER film_server;

서버 server_07를 통해 접근할 외부 테이블 measurement_y2016m07을, 범위 파티션 테이블 measurement의 파티션으로 생성하기:

CREATE FOREIGN TABLE measurement_y2016m07
    PARTITION OF measurement FOR VALUES FROM ('2016-07-01') TO ('2016-08-01')
    SERVER server_07;

Compatibility

CREATE FOREIGN TABLE 명령은 대체로 SQL 표준을 따르는 명령이에요. 다만 CREATE TABLE과 마찬가지로 NULL 제약과 0컬럼 외부 테이블이 허용돼요. 컬럼 기본값을 지정하는 능력도 PostgreSQL 확장이에요. PostgreSQL이 정의한 형태의 테이블 상속은 비표준이에요. 이 명령에서 지원되는 LIKE 절도 비표준이에요.

더 알아보기 (Learn more)