UNIQUE는 “값이 같음(점 동등성)”만 막을 수 있어 “구간이 겹침”은 표현 불가 → exclusion constraint가 이 공백을 메움btree_gist 확장tstzrange(타임존 포함 시각)·tsrange·daterange·int4range 등[)(끝 제외, 기본)·[]·(]·()&&(겹침)·@>(포함)·<@(포함됨)·-|-(인접)multirange(PG 14+): tstzmultirange 등 불연속 구간 표현&&)을 못 다룸=)을 지원하지 않음btree_gist가 스칼라용 GiST 연산자 클래스를 추가 → room_id WITH = 와 during WITH && 를 한 제약에 섞을 수 있게 함CREATE EXTENSION btree_gist; -- 스칼라 = 를 GiST에서 쓰기 위해
CREATE TABLE reservation (
room_id int,
during tstzrange,
EXCLUDE USING gist (room_id WITH =, during WITH &&) -- 같은 방 + 시간 겹침 금지
);
INSERT INTO reservation VALUES (1, '[2026-01-01 10:00, 2026-01-01 11:00)');
INSERT INTO reservation VALUES (1, '[2026-01-01 10:30, 2026-01-01 11:30)');
-- ERROR: conflicting key value violates exclusion constraint (SQLSTATE 23P01)
EXCLUDE USING gist (A WITH =, B WITH &&) = “A가 같고 B가 겹치는 행은 공존 불가”exclusion_violation(23P01)으로 거부UNIQUE + 앱 레벨 충돌 검사로는 못 막는 동시 삽입 레이스를 선언적으로 해결[) 의 중요성[)(끝 제외) → [10:00, 11:00) 과 [11:00, 12:00) 은 겹치지 않음btree_gist 확장 설치가 전제 (스칼라 =와 범위 && 혼용 시)DEFERRABLE INITIALLY DEFERRED로 커밋 시점 검사 가능 (일괄 갱신 등)