CREATE HYBRID TABLE

CREATE HYBRID TABLE

현재/지정한 스키마에 새 하이브리드 테이블(hybrid table)을 만들거나 기존 테이블을 교체하는 명령이에요. 하이브리드 테이블은 행 기반 저장소를 사용해 포인트 조회(point lookup)와 단일 행 기반 DML에 최적화된 테이블이에요. 하이브리드 테이블을 만들 때는 하나 이상의 컬럼에 PRIMARY KEY 제약 조건을 정의해야 해요.

출처: 문서

본문

테이블은 여러 컬럼을 가질 수 있으며, 각 컬럼 정의는 이름, 데이터 타입, 선택적으로 다음 여부로 구성돼요:

  • NOT NULL 값 요구.
  • 기본값 또는 identity 컬럼 여부.
  • 인라인 제약 조건 여부.

하이브리드 테이블을 만들 수 있는 CREATE TABLE 변형도 사용할 수 있어요:

  • CREATE HYBRID TABLE … AS SELECT (CTAS): 데이터가 채워진 테이블 생성.
  • CREATE HYBRID TABLE … LIKE: 기존 하이브리드 테이블의 빈 복사본 생성.

구문 (Syntax)

CREATE [ OR REPLACE ] HYBRID TABLE [ IF NOT EXISTS ] <table_name>
  ( <col_name> <col_type>
    [
      {
        DEFAULT <expr>
        | { AUTOINCREMENT | IDENTITY }
          [
            {
              ( <start_num> , <step_num> )
              | START <num> INCREMENT <num>
            }
          ]
          [ { ORDER | NOORDER } ]
      }
    ]
    [ NOT NULL ]
    [ inlineConstraint ]
    [ COLLATE '<collation_specification>' ]
    [ COMMENT '<string_literal>' ]
    [ , <col_name> <col_type> [ ... ] ]
    [ , outoflineConstraint ]
    [ , outoflineIndex ]
    [ , ... ]
  )
  [ COMMENT = '<string_literal>' ]

여기서:

inlineConstraint ::=
  [ CONSTRAINT <constraint_name> ]
  { UNIQUE | PRIMARY KEY | { [ FOREIGN KEY ] REFERENCES <ref_table_name> [ ( <ref_col_name> ) ] } }
  [ <constraint_properties> ]

outoflineConstraint ::=
  [ CONSTRAINT <constraint_name> ]
  { UNIQUE [ ( <col_name> [ , <col_name> , ... ] ) ]
    | PRIMARY KEY [ ( <col_name> [ , <col_name> , ... ] ) ]
    | [ FOREIGN KEY ] [ ( <col_name> [ , <col_name> , ... ] ) ]
      REFERENCES <ref_table_name> [ ( <ref_col_name> [ , <ref_col_name> , ... ] ) ]
  }
  [ <constraint_properties> ]
  [ COMMENT '<string_literal>' ]

outoflineIndex ::=
  INDEX <index_name> ( <col_name> [ , <col_name> , ... ] )
    [ INCLUDE ( <col_name> [ , <col_name> , ... ] ) ]

필수 매개변수

  • <name>: 테이블의 식별자예요. 생성되는 스키마 내에서 고유해야 해요.
  • <col_name>: 컬럼 식별자를 지정해요. 표준 예약 키워드 외에도 CURRENT_DATE, CURRENT_ROLE, CURRENT_TIME, CURRENT_TIMESTAMP, CURRENT_USER 같은 ANSI 표준 컨텍스트 함수 예약 키워드는 컬럼으로 사용할 수 없어요.
  • <col_type>: 컬럼의 데이터 타입을 지정해요.
  • PRIMARY KEY ( col_name [ , ... ] ): 테이블의 필수 기본 키 제약 조건을 지정해요. 컬럼 정의 내(인라인) 또는 별도(아웃오브라인)로 지정할 수 있어요.

선택 매개변수

  • DEFAULT ... 또는 AUTOINCREMENT ...: INSERT 또는 CTAS 문으로 값이 명시적으로 지정되지 않을 때 컬럼에 자동으로 삽입되는 기본값을 지정해요.
    • DEFAULT expr: 컬럼 기본값을 지정된 표현식으로 정의해요. 상수 값, 단순 표현식, 시퀀스 참조(seq_name.NEXTVAL)일 수 있어요. 서브쿼리, 집계, 창 함수, 외부 함수는 참조할 수 없어요.
    • { AUTOINCREMENT | IDENTITY } [ { ( start_num , step_num ) | START num INCREMENT num } ] [ { ORDER | NOORDER } ]: AUTOINCREMENT를 사용하면 기본값이 지정된 숫자에서 시작해 각 연속 값이 자동 생성돼요. 생성된 값은 고유함이 보장돼요. ORDER/NOORDER는 생성 값의 순서 보장 여부를 지정해요. NOORDER가 기본이고 포인트 쓰기에 훨씬 더 나은 성능을 제공해요. AUTOINCREMENTIDENTITY는 동의어예요. start와 step의 기본값은 각각 1이에요. DEFAULTAUTOINCREMENT는 상호 배타적이에요.
  • CONSTRAINT ...: 테이블의 지정된 컬럼에 대한 인라인/아웃오브라인 제약 조건을 정의해요. UNIQUE와 FOREIGN KEY는 선택 사항이에요.
  • COLLATE 'collation_specification': 문자열 비교 같은 컬럼 작업에 사용할 정렬(collation)을 지정해요. 인덱스되지 않은 텍스트 컬럼에만 적용돼요.
  • INDEX index_name ( col_name [ , ... ] ): 테이블의 하나 이상의 컬럼에 대한 보조 인덱스를 지정해요. (컬럼에 제약 조건을 정의하면 그 컬럼에 인덱스가 자동 생성돼요.) 다음 컬럼에는 인덱스를 정의할 수 없어요: 반정형 컬럼(VARIANT, OBJECT, ARRAY), 지리 공간 컬럼(GEOGRAPHY, GEOMETRY) 또는 VECTOR 컬럼, TIMESTAMP_TZ 컬럼(또는 TIMESTAMP_TZ로 해석되는 TIMESTAMP). TIMESTAMP_NTZ는 지원돼요.
  • INCLUDE ( col_name [ , ... ] ): 보조 인덱스의 포함 컬럼을 지정해요. SELECT 목록에 자주 있지만 WHERE 조건 목록에는 없는 컬럼 집합에 유용해요. INCLUDE 컬럼은 반정형/지리 공간 컬럼일 수 없어요.
  • COMMENT = 'string_literal': 컬럼, 제약 조건, 또는 테이블 수준의 주석을 지정해요.

접근 제어 요구 사항

권한 객체 참고
CREATE HYBRID TABLE 스키마
SELECT 테이블, 외부 테이블, 뷰 복제 또는 CTAS 실행 시 쿼리할 객체에만 필요.
APPLY 마스킹 폴리시, 행 접근 폴리시, 태그 테이블 생성 시 마스킹 폴리시/행 접근 폴리시/객체 태그를 적용할 때만 필요.

사용법 참고 사항

  • 기존 하이브리드 테이블을 재생성/교체하기 전에 GET_DDL 함수로 정의를 확인하세요.
  • 임시 또는 일시(transient) 하이브리드 테이블을 만들 수 없어요. 임시 스키마/데이터베이스 내에서도 만들 수 없어요.
  • 같은 스키마에는 같은 이름의 테이블과 뷰가 공존할 수 없어요.
  • OR REPLACE를 사용하면 기존 테이블에 DROP TABLE을 수행한 다음 같은 이름으로 만드는 것과 동일해요. 드롭과 생성은 단일 원자 작업으로 발생해요.
  • 테이블을 재생성/교체하면 변경 데이터(change data)가 드롭돼요.
  • OR REPLACEIF NOT EXISTS 절은 상호 배타적이에요.
  • ANSI 예약 함수 이름(CURRENT_DATE 등)은 컬럼 이름으로 사용할 수 없어요.

하이브리드 테이블의 제약 조건

  • 하이브리드 테이블은 PRIMARY KEY 제약 조건과 함께 생성해야 해요.
  • 다중 컬럼(복합) 기본 키가 지원돼요. 아웃오브라인으로 정의해요:
CREATE OR REPLACE HYBRID TABLE ht2pk (
  col1 INTEGER NOT NULL,
  col2 INTEGER NOT NULL,
  col3 VARCHAR,
  CONSTRAINT pkey_1 PRIMARY KEY (col1, col2)
  );
  • PRIMARY KEY, UNIQUE, FOREIGN KEY 제약 조건은 모두 강제되며 NOT ENFORCED 속성을 설정할 수 없어요.
  • PRIMARY KEY, UNIQUE, FOREIGN KEY 제약 조건은 자체 기본 인덱스를 구축해요. 보조(커버링) 인덱스도 명시적으로 정의할 수 있어요.
  • 제약 조건은 행 수준에서 강제돼요 (문/트랜잭션 수준의 지연 수정 아님).
  • PRIMARY KEY 제약 조건은 테이블 생성 시에만 정의할 수 있어요. 기존 하이브리드 테이블에는 ALTER TABLE로 UNIQUE와 FOREIGN KEY만 추가/제거할 수 있어요.
  • 컬럼을 UNIQUE로 수정할 수는 없어요. 아웃오브라인 ALTER TABLE … ADD CONSTRAINT 구문을 사용하세요.
  • FOREIGN KEY 특정 규칙:
    • 기본 키를 참조하는 하이브리드 테이블의 외래 키는 NULL일 수 없어요. NULL을 로드하면 제약 오류로 실패해요.
    • FOREIGN KEY 제약 조건은 같은 데이터베이스에 속한 하이브리드 테이블 사이에서만 지원돼요.
    • FOREIGN KEY 관계가 존재하는 한 참조 테이블을 TRUNCATE할 수 없어요.
    • FOREIGN KEY는 부분 일치, 지연 가능(deferrable) 동작을 지원하지 않아요.
    • FOREIGN KEY는 DELETE/UPDATE 작업에 RESTRICT와 NO ACTION 속성만 지원해요.

기존 하이브리드 테이블에 제약 조건 추가/제거

UNIQUE/FOREIGN KEY 제약 조건을 테이블을 오프라인으로 만들지 않고 추가/제거할 수 있어요. Snowflake가 백그라운드에서 제약 조건을 지탱하는 인덱스를 구축하며 테이블은 계속 사용 가능해요.

ALTER TABLE player ADD CONSTRAINT fk_player_team
  FOREIGN KEY (team_id) REFERENCES team(team_id);

인덱스 구축 추적: SHOW INDEXES IN TABLE player;status 컬럼이 구축 중에는 BUILD IN PROGRESS, 완료되면 ACTIVE를 보고해요. 한 번에 테이블당 하나의 인덱스만 구축해요.

기존 데이터가 제약 조건을 위반하면 ALTER TABLE은 여전히 성공하지만(백그라운드 검증), SHOW INDEXESBUILD VALIDATION FAILURE를 보고해요. 이 상태의 제약 조건은 새 쓰기는 강제하지만 기존 행은 검증되지 않은 채 남아요. 복구하려면 제약 조건을 드롭하고 문제 행을 수정한 뒤 다시 추가하세요.

하이브리드 테이블 컬럼의 정렬(Collations)

  • PRIMARY KEY 컬럼과 다른 인덱스된 컬럼에는 정렬이 지원되지 않아요.
  • 인덱스하지 않을 계획이고 문자 데이터 타입이면 COLLATE 절을 지정할 수 있어요:
CREATE OR REPLACE HYBRID TABLE ht1 (c1 INT PRIMARY KEY, c2 VARCHAR(10) COLLATE 'de');
  • 계정/스키마/데이터베이스 수준에 기본 정렬이 설정되어 있을 때 DEFAULT_DDL_COLLATION = '' 구문으로 하이브리드 테이블 컬럼의 정렬을 비활성화할 필요가 있을 수 있어요:
ALTER SCHEMA ht SET DEFAULT_DDL_COLLATION = 'de';

CREATE OR REPLACE HYBRID TABLE ht2 (c1 INT PRIMARY KEY, c2 VARCHAR(10),
  INDEX idx_c2 (c2))
  DEFAULT_DDL_COLLATION = '';

CREATE HYBRID TABLE … AS SELECT (CTAS)

쿼리 결과를 포함하는 새 하이브리드 테이블을 만들어요:

CREATE [ OR REPLACE ] HYBRID TABLE <table_name> [ ( <col_name> [ <col_type> ] , <col_name> [ <col_type> ] , ... ) ]
  [ ... ]
  AS <query>

CTAS로 하이브리드 테이블을 만들 때는 테이블 스키마를 명시적으로 정의해야 해요. 쿼리 정의 전에 컬럼 정의, PRIMARY KEY 제약 조건, 다른 제약 조건, 보조 인덱스를 지정해야 해요. 새 하이브리드 테이블의 스키마는 SELECT 문에서 추론할 수 없어요. 컬럼 이름 수는 쿼리의 SELECT 목록 항목 수와 일치해야 해요.

CREATE HYBRID TABLE … LIKE

기존 하이브리드 테이블과 동일한 컬럼 정의를 가지지만 데이터는 복사하지 않는 새 하이브리드 테이블을 만들어요. 컬럼 이름, 타입, 기본값, 제약 조건, 인덱스가 복사돼요:

CREATE [ OR REPLACE ] HYBRID TABLE <table_name> LIKE <source_hybrid_table>
  [ ... ]

LIKE는 소스 테이블 유형으로 하이브리드 테이블만 지원해요.

예제 (Examples)

customer_id를 기본 키로, email에 UNIQUE 제약 조건, full_name에 보조 인덱스를 가진 하이브리드 테이블을 만들어요:

CREATE HYBRID TABLE mytable (
  customer_id INT AUTOINCREMENT PRIMARY KEY,
  full_name VARCHAR(255),
  email VARCHAR(255) UNIQUE,
  extended_customer_info VARIANT,
  INDEX index_full_name (full_name)
);

행을 삽입해요:

INSERT INTO mytable (customer_id, full_name, email, extended_customer_info)
  SELECT 100, 'Jane Doe', '[email protected]',
    parse_json('{"address": "1234 Main St", "city": "San Francisco", "state": "CA", "zip":"94110"}');

기본 키는 고유해야 해요. 같은 기본 키를 다시 삽입하면 다음 오류가 발생해요: 200001 (22000): Primary key already exists. 같은 이메일을 두 번 삽입하면: Duplicate key value violates unique constraint "SYS_INDEX_MYTABLE_UNIQUE_EMAIL".

테이블 속성과 메타데이터를 봐요 (is_hybrid 컬럼에 주목):

SHOW TABLES LIKE 'mytable';
SHOW HYBRID TABLES;
DESCRIBE TABLE mytable;

데이터를 조회해요:

SELECT customer_id, full_name, email, extended_customer_info
  FROM mytable
  WHERE extended_customer_info['state'] = 'CA';

기본 키/외래 키 관계를 가진 두 하이브리드 테이블 생성

team 테이블에는 team_id PRIMARY KEY, player 테이블에는 team_id FOREIGN KEY가 있어요:

CREATE OR REPLACE HYBRID TABLE team
  (team_id INT PRIMARY KEY,
  team_name VARCHAR(40),
  stadium VARCHAR(40));

CREATE OR REPLACE HYBRID TABLE player
  (player_id INT PRIMARY KEY,
  first_name VARCHAR(40),
  last_name VARCHAR(40),
  team_id INT,
  FOREIGN KEY (team_id) REFERENCES team(team_id));

team에 없는 ID 3을 참조하거나 NULL 외래 키를 삽입하면 실패해요:

INSERT INTO team VALUES (1, 'Bayern Munich', 'Allianz Arena');
INSERT INTO player VALUES (100, 'Harry', 'Kane', 1);
INSERT INTO player VALUES (301, 'Gareth', 'Bale', 3);  -- fails
INSERT INTO player VALUES (200, 'Tommy', 'Atkins', NULL);  -- fails

NULL 외래 키 거부에 대한 우회 방법은 team 테이블에 팀 ID 0의 “더미” 행을 삽입하고 NULL 대신 0을 사용하는 것이에요:

INSERT INTO team VALUES (0, 'Unknown', 'Unknown');
INSERT INTO player VALUES (200, 'Tommy', 'Atkins', 0);

기본 키 컬럼에 주석이 있는 하이브리드 테이블 생성

CREATE OR REPLACE HYBRID TABLE ht1pk
  (COL1 NUMBER(38,0) NOT NULL COMMENT 'Primary key',
  COL2 NUMBER(38,0) NOT NULL,
  COL3 VARCHAR(16777216),
  CONSTRAINT PKEY_1 PRIMARY KEY (COL1));

DESCRIBE TABLE ht1pk;

더 알아보기 (Learn more)