CHECK 제약조건은 일종의 테이블 입구에 있는 경비원이야. 네가 테이블에 추가하는 데이터가 어떤 조건을 만족하는지 보장해줘. 만약 조건을 어기는 데이터를 테이블에 넣으려고 하면, 데이터베이스가 그 데이터를 거부해.
예를 들어, 네가 독일에서 가게를 열고 싶다고 해보자. 근데 법적으로 일요일은 쉬는 날이고, 그날은 영업이 금지되어 있어. 이 제한이 바로 데이터베이스의 CHECK랑 비슷해. 네가 가게 스케줄을 일주일 내내 영업으로 설정하려고 하면, 시스템이 바로 이렇게 말하지: "Nein, nein, 일요일은 안 돼. 이런 스케줄은 통과 못 해!"
데이터베이스도 마찬가지야. CHECK 규칙을 어기는 값을 넣으려고 하면, 시스템이 그걸 막아서 "논리적 오류"가 데이터에 들어가는 걸 방지해.
CHECK가 왜 필요할까?
- 데이터 품질 유지:
CHECK는 테이블에 잘못되거나 논리에 맞지 않는 정보가 들어오는 걸 막아줘. - 오류 가능성 줄이기: 데이터를 직접 일일이 확인하지 않아도, 데이터베이스가 알아서 검사해주니까 실수할 확률이 줄어들어.
- 로직의 독립성: 검증 규칙을 데이터베이스 구조에 직접 넣을 수 있어서, 이걸 애플리케이션 코드에 맡기지 않아도 돼.
CHECK는 어떻게 동작할까?
CHECK 제약조건은 테이블을 만들 때 지정하거나, 나중에 ALTER TABLE 명령으로 추가할 수도 있어. 기본 문법은 이래:
CREATE TABLE 테이블 (
컬럼 데이터_타입 CHECK (조건)
);
조건은 해당 컬럼의 각 값에 대해 만족해야 하는 논리식이야. 만약 조건을 어기면, 데이터베이스가 에러를 내.
예시 1: 값의 범위 체크
학생들의 나이(age)가 16살 이상 100살 이하인 students 테이블을 만들어보자:
CREATE TABLE students (
id SERIAL PRIMARY KEY,
name VARCHAR(100) NOT NULL,
age INTEGER CHECK (age >= 16 AND age <= 100)
);
이제 만약 12살인 학생을 넣으려고 하면, 데이터베이스가 바로 "딱 걸렸어!"라고 해:
INSERT INTO students (name, age)
VALUES ('Maria Chi', 12);
에러:
ERROR: new row for relation "students" violates check constraint "students_age_check"
DETAIL: Failing row contains (1, Maria Chi, 12).
맞아, 데이터베이스는 엄격한 문지기야. 16살 안 되면 못 들어와.
예시 2: 데이터 형식 체크
이번엔 emails 테이블에 이메일 주소를 저장한다고 해보자. 이메일에 @가 꼭 들어가야 한다고 체크하고 싶어(간단한 방식이지만):
CREATE TABLE emails (
id SERIAL PRIMARY KEY,
email VARCHAR(255) CHECK (email LIKE '%@%')
);
조건에 맞지 않는 잘못된 주소를 넣어보자:
INSERT INTO emails (email)
VALUES ('notanemail.com');
에러:
ERROR: new row for relation "emails" violates check constraint "emails_email_check"
DETAIL: Failing row contains (1, notanemail.com).
모든 데이터에 @가 들어가면 에러 없이 잘 들어가:
INSERT INTO emails (email)
VALUES ('example@student.com');
이 쿼리는 성공적으로 실행돼.
예시 3: 여러 컬럼 조건 체크
CHECK 제약조건은 한 컬럼뿐 아니라 여러 컬럼이 얽힌 논리식도 검사할 수 있어. 예를 들어 employees 테이블에서 급여(salary)가 보너스(bonus)보다 커야 한다고 해보자:
CREATE TABLE employees (
id SERIAL PRIMARY KEY,
name VARCHAR(100) NOT NULL,
salary NUMERIC CHECK (salary > 0),
bonus NUMERIC CHECK (bonus >= 0),
CHECK (salary > bonus)
);
이제 보너스가 급여보다 많은 직원을 추가하려고 하면, 데이터베이스가 허락하지 않아:
INSERT INTO employees (name, salary, bonus)
VALUES ('Otto Lin', 3000, 4000);
에러:
ERROR: new row for relation "employees" violates check constraint "employees_salary_bonus_check"
DETAIL: Failing row contains (1, Otto Lin, 3000, 4000).
실전 활용
CHECK 제약조건은 비즈니스 로직이 데이터 제한과 밀접하게 연결되어 있을 때 특히 유용해. 예를 들면:
- 온라인 쇼핑몰: 가격이 마이너스인 상품 추가 금지.
- 교육 플랫폼: 수강생 나이 체크.
- 의료 시스템: 환자 체온이 허용 범위 안에 있는지 확인.
이런 검증은 단순한 보안 레이어가 아니라, 개발자랑 사용자 모두의 시간과 스트레스를 줄여줘.
특징과 흔한 실수
CHECK를 쓸 때는 다음을 꼭 기억해:
CHECK의 논리식은 테이블의 모든 행에 대해 참이어야 해. 만약 한 행이라도 규칙을 어기면, 제약조건 추가 전에 그 행을 먼저 고쳐야 해.입력값이
NULL이면 체크가 실행되지 않아. 즉,CHECK (age >= 18)은age = NULL일 때 에러를 내지 않아. 왜냐하면NULL이 들어간 식은 무조건 불확정이 되거든.NULL을 막고 싶으면NOT NULL도 같이 써줘야 해.CHECK에 복잡한 조건을 넣으면, 특히 큰 테이블에서 데이터 추가나 수정할 때 성능이 떨어질 수 있어.
GO TO FULL VERSION