제약 조건 개요
제약 조건 개요 (Overview of constraints)
제약 조건(Constraint)은 테이블에 저장된 데이터의 무결성과 일관성을 보장하는 규칙이에요. 이 페이지에서는 Snowflake가 지원하는 제약 조건의 유형(PRIMARY KEY, UNIQUE, FOREIGN KEY, NOT NULL, CHECK)과, 표준 테이블과 하이브리드 테이블에서 제약 조건이 어떻게 다르게 적용되는지를 정리해요.
본문
Snowflake는 다음과 같은 제약 조건 기능을 제공해요.
- ANSI SQL 표준의 제약 조건 유형. 자세한 내용은 지원되는 제약 조건 유형을 참고해요.
- 이름이 있는(named) 제약 조건.
- 단일 컬럼 및 다중 컬럼 제약 조건.
- 인라인(inline) 및 아웃오브라인(out-of-line) 제약 조건 생성.
- 제약 조건의 생성, 수정, 삭제.
자세한 내용은 CREATE | ALTER TABLE … CONSTRAINT를 참고해요.
지원되는 제약 조건 유형
Snowflake는 ANSI SQL 표준의 다음 제약 조건 유형을 지원해요.
- PRIMARY KEY: 컬럼의 모든 값이 고유하고, 컬럼이 NULL 값을 저장할 수 없음을 보장해요. 기본 키는 테이블의 각 행을 고유하게 식별해요.
- UNIQUE: 컬럼의 모든 값이 고유함을 보장해요. PRIMARY KEY 제약 조건과 달리, UNIQUE 제약 조건이 있는 컬럼은 NULL 값을 가질 수 있어요.
- FOREIGN KEY: 컬럼 또는 컬럼 집합의 값이 다른 테이블 또는 같은 테이블의 값과 일치하도록 요구해 참조 무결성(referential integrity)을 강제해요.
- NOT NULL: 컬럼이 NULL 값을 저장할 수 없음을 보장해요.
- CHECK: SQL 표현식을 테이블의 하나 이상의 컬럼에 삽입되거나 업데이트될 수 있는 값에 대한 조건으로 강제해요. 자세한 내용은 CHECK 제약 조건을 참고해요.
테이블은 여러 개의 unique 키와 foreign key를 가질 수 있지만, primary key는 하나만 가질 수 있어요. PRIMARY KEY 제약 조건은 컬럼이 NOT NULL이면서 동시에 UNIQUE임을 의미해요.
모든 foreign key는 foreign key의 각 컬럼 타입과 일치하는 primary 또는 unique 키를 참조해야 해요. foreign key의 primary key는 foreign key와 다른 테이블이나 같은 테이블에 있을 수 있어요. 하이브리드 테이블(hybrid tables)에 FOREIGN KEY 제약 조건을 정의할 때는 테이블들이 같은 데이터베이스에 있어야 해요.
다음 표는 제약 조건의 강제(enforcement) 여부와 필수(required) 여부에 대한 표준 테이블과 하이브리드 테이블의 동작 차이를 요약해요.
- 제약 조건이 강제(enforced) 된다는 것은 특정 방식으로 컬럼이 업데이트되는 것을 보호한다는 뜻이에요. 예를 들어 NOT NULL로 선언된 컬럼은 NULL 값을 포함할 수 없어요. NOT NULL 컬럼에 NULL 값을 복사하거나 삽입하면 오류가 발생해요. 하이브리드 테이블에서는 PRIMARY KEY, FOREIGN KEY, UNIQUE 제약 조건에 NOT ENFORCED 속성을 설정할 수 없어요. 이를 설정하면
invalid constraint property오류가 발생해요. - 제약 조건이 필수(required) 라는 것은 테이블의 하나 이상의 컬럼이 반드시 그러한 제약 조건을 가져야 한다는 뜻이에요. 이는 하이브리드 테이블의 PRIMARY KEY 제약 조건에만 해당해요.
| 기능 | 하이브리드 테이블 | 표준 테이블 |
|---|---|---|
| PRIMARY KEY 제약 조건 | 필수, 강제 | 선택, 강제 안 함 |
| FOREIGN KEY 제약 조건 | 선택, 강제(참조 무결성) | 선택, 강제 안 함 |
| UNIQUE 제약 조건 | 선택, 강제 | 선택, 강제 안 함 |
| NOT NULL 제약 조건 | 선택, 강제 | 선택, 강제 |
| CHECK 제약 조건 | 지원 안 함 | 선택, 강제 |
테이블 제약 조건
Snowflake는 permanent, transient, temporary, hybrid 테이블에서 제약 조건을 지원해요. 모든 데이터 타입의 컬럼에 제약 조건을 정의할 수 있고, 하나의 제약 조건에 원하는 만큼의 컬럼을 포함할 수 있어요.
제약 조건에 대한 고려 사항은 다음과 같아요.
- CREATE TABLE … LIKE 또는 CREATE TABLE … CLONE으로 테이블을 복사하면, foreign key를 포함한 테이블의 기존 제약 조건이 모두 새 테이블로 복사돼요. CREATE TABLE … CLONE은 하이브리드 테이블에서는 지원되지 않아요.
- 하이브리드 테이블의 경우, ALTER TABLE로 UNIQUE나 FOREIGN KEY 제약 조건을 추가하는 것은 온라인(online) 작업이며 테이블에 이미 있는 행도 함께 검증돼요. 자세한 내용은 기존 하이브리드 테이블에 제약 조건 추가·삭제를 참고해요.
- DROP, UNDROP, GET_DDL 같은 추가 명령과 함수는 제약 조건이 있는 테이블에서 지원돼요. 스키마와 데이터베이스에서도 지원돼요.
Snowflake Time Travel의 경우, 테이블의 이전 버전을 복사할 때 테이블 제약 조건의 현재 버전이 사용돼요. Snowflake는 테이블 메타데이터에 제약 조건의 이전 버전을 저장하지 않기 때문이에요.
단일 컬럼 및 다중 컬럼 제약 조건
같은 테이블의 단일 컬럼 또는 여러 컬럼에 제약 조건을 정의할 수 있어요.
다중 컬럼 제약 조건(복합 primary key 또는 unique key)의 경우, 컬럼은 순서가 있고 각 컬럼은 해당하는 키 시퀀스(key sequence)를 가져요.
인라인 및 아웃오브라인 제약 조건
제약 조건은 테이블 생성 또는 수정 시 인라인 또는 아웃오브라인으로 정의돼요.
- 인라인 제약 조건은 컬럼 정의의 일부로 만들어지며, 단일 컬럼 제약 조건에만 사용할 수 있어요.
- 아웃오브라인 제약 조건은 제약 조건이 만들어지는 컬럼을 지정하는 별도의 절로 정의돼요. 단일 컬럼 또는 다중 컬럼 제약 조건을 만들 때, 그리고 기존 컬럼에 제약 조건을 만들 때 사용할 수 있어요.
GET_DDL에서의 제약 조건
GET_DDL이 반환하는 SQL 문에는 제약 조건을 정의하는 절이 포함돼요. 단, 다음을 주의하세요.
NOT NULL,DEFAULT같은 단일 컬럼 제약 조건은 컬럼 정의와 함께 인라인으로 재구성돼요.- unique, primary, foreign key 같은 테이블 제약 조건은 단일 컬럼으로 구성되더라도 항상 아웃오브라인 제약 조건으로 재구성돼요.
- 이름이 없는 제약 조건(즉, 시스템 생성 이름을 가진 제약 조건)의 경우 GET_DDL은 시스템 생성 이름을 반환하지 않아요.
CHECK 제약 조건
CHECK 제약 조건은 테이블의 하나 이상의 컬럼에 삽입되거나 업데이트될 수 있는 값에 대한 조건으로 SQL 표현식을 강제해요. 예를 들어 CHECK 제약 조건은 테이블의 quantity 컬럼이 0보다 큰 값만 포함하도록, 또는 salary 컬럼이 특정 범위의 값만 포함하도록 보장할 수 있어요.
CONSTRAINT 절을 사용해 다음 SQL 명령에서 CHECK 제약 조건을 지정할 수 있어요.
CHECK_CONSTRAINTS 뷰를 쿼리해 기존 CHECK 제약 조건에 대한 정보를 볼 수 있어요.
CHECK 제약 조건은 다음 DML 연산 중에 강제돼요.
조건이 TRUE 또는 NULL로 평가되면 DML 연산이 진행돼요. 조건이 FALSE로 평가되면 CHECK 제약 조건이 실패해요.
CHECK 제약 조건의 예제는 표준 테이블의 제약 조건 예제를 참고해요.
사용 메모
- CHECK 제약 조건은 항상 강제돼요.
- 다음 ALTER TABLE 명령과 Iceberg 등가 명령을 사용해 CHECK 제약 조건을 다룰 수 있어요.
- ALTER TABLE … RENAME CONSTRAINT
- ALTER TABLE … ADD [ CONSTRAINT <constraint_name> ] CHECK ( <expr> ) ENABLE [ VALIDATE | NOVALIDATE ]
- CHECK 제약 조건의 기본값인 ENABLE VALIDATE는 명령을 실행한 뒤의 모든 기존 행과 삽입·업데이트되는 모든 행에 제약 조건을 강제해요. ENABLE VALIDATE는 기존 테이블이 아닌 새 테이블에만 지원돼요.
- ENABLE NOVALIDATE는 명령 실행 후 삽입·업데이트되는 모든 행에는 제약 조건을 강제하지만, 기존 행에는 강제하지 않아요.
- ALTER TABLE … ALTER CONSTRAINT <constraint_name> ENABLE [ VALIDATE | NOVALIDATE ]
CHECK 제약 조건을 NOVALIDATE에서 VALIDATE로 변경하면, VALIDATE로 바뀌기 전에 모든 기존 행에 제약 조건이 강제돼요.
- ALTER TABLE … DROP CONSTRAINT
- 다음 ALTER TABLE 명령과 Iceberg 등가 명령은 CHECK 제약 조건이 정의된 컬럼에 대해 동작할 수 있어요.
- ALTER TABLE … ALTER COLUMN
CHECK 제약 조건을 수정하지 않는 연산만 지원돼요.
- ALTER TABLE … RENAME COLUMN
이름이 변경된 컬럼을 참조하는 CHECK 제약 조건은 새 컬럼 이름을 사용하도록 암시적으로 업데이트돼요.
- ALTER TABLE … DROP COLUMN
드롭되는 컬럼이 다른 컬럼도 참조하는 기존 CHECK 제약 조건에서 사용된다면 연산이 실패해요. 이 경우 컬럼을 삭제하기 전에 제약 조건을 삭제하세요.
- 수집(ingestion) 중에 레코드가 CHECK 제약 조건을 위반하면, 유효하지 않은 레코드를 처음 만나는 순간 전체 배치(batch) 연산이 실패해요.
제한 사항
- 표준 테이블과 Snowflake 관리 Iceberg 테이블만 CHECK 제약 조건을 지원해요. 하이브리드 테이블 같은 다른 유형의 테이블은 CHECK 제약 조건을 지원하지 않아요.
- 기존 CHECK 제약 조건과 연결된 표현식은 ALTER TABLE 명령으로 수정할 수 없어요. 표현식을 수정하려면 CHECK 제약 조건을 드롭하고 다시 만들어야 해요.
- CREATE OR ALTER TABLE 명령에서는 CHECK 제약 조건을 지정할 수 없어요.
- 다음 연산은 CHECK 제약 조건을 지원하지 않아요.
- CHECK 제약 조건이 있는 테이블에 COPY INTO를 시도하면 연산이 실패해요.
- CHECK 제약 조건이 있는 대상 테이블로 파이프(pipe)를 만들려고 하면 연산이 실패해요.
- 클래식 아키텍처의 Snowpipe Streaming은 CHECK 제약 조건이 있는 테이블을 지원하지 않아요. 그러한 테이블에서 채널을 열려고 하면 실패해요. 고성능 아키텍처의 Snowpipe Streaming은 CHECK 제약 조건을 지원하고 수집 중에 강제해요.
- CHECK 제약 조건이 있는 Iceberg 테이블에서 외부 쓰기(external writes)를 시도하면 연산이 실패해요.
더 알아보기 (Learn more)
- 제약 조건 만들기 — 제약 조건 정의 방법
- 제약 조건 수정하기 — 기존 제약 조건 변경
- 제약 조건 삭제하기 — 제약 조건 제거
- CREATE TABLE — 테이블 생성 명령