제약조건 체험
사용 테이블
customers — 고객 (등급, 포인트, 가입채널)
products — 상품 (이름, 가격, 재고, 브랜드)
reviews — 리뷰 (평점, 내용)
wishlists — 위시리스트 (고객-상품)
학습 범위
PRIMARY KEY, UNIQUE, FOREIGN KEY, CHECK, NOT NULL, ON CONFLICT, UPSERT
1. 이미 존재하는 id로 상품을 삽입하면 어떻게 될까요?
이미 존재하는 id로 상품을 삽입하면 어떻게 될까요?
힌트 1: 이미 존재하는 id 값으로 INSERT하면 PRIMARY KEY의 고유성 제약이 위반됩니다.
정답
2. 이미 등록된 이메일로 고객을 만들면?
이미 등록된 이메일로 고객을 만들면?
힌트 1: UNIQUE 제약이 걸린 칼럼에 이미 존재하는 값을 넣으면 중복 에러가 발생합니다.
정답
3. 존재하지 않는 카테고리에 상품을 넣으면?
존재하지 않는 카테고리에 상품을 넣으면?
힌트 1: FOREIGN KEY는 부모 테이블에 존재하는 값만 허용합니다. SQLite에서는 PRAGMA foreign_keys = ON 필요.
정답
4. 가격을 음수로 설정하면?
가격을 음수로 설정하면?
힌트 1: CHECK(price >= 0) 제약이 정의되어 있으면, 음수 값 삽입 시 거부됩니다.
정답
5. 고객 등급을 허용되지 않은 값으로 설정하면?
고객 등급을 허용되지 않은 값으로 설정하면?
힌트 1: CHECK(grade IN ('BRONZE','SILVER','GOLD','VIP')) 같은 허용 목록 제약은 목록에 없는 값을 거부합니다.
정답
6. 필수 칼럼을 비우면?
필수 칼럼을 비우면?
힌트 1: NOT NULL 제약이 있는 칼럼에 NULL을 넣으면 에러가 발생합니다.
정답
7. 같은 고객이 같은 상품을 위시리스트에 두 번 추가하면?
같은 고객이 같은 상품을 위시리스트에 두 번 추가하면?
힌트 1: (customer_id, product_id) 두 칼럼의 조합이 UNIQUE면, 같은 조합을 두 번째 삽입할 때 에러가 납니다.
정답
8. 리뷰 평점을 0점이나 6점으로 주면?
리뷰 평점을 0점이나 6점으로 주면?
힌트 1: CHECK(rating BETWEEN 1 AND 5) 제약은 범위를 벗어나는 값을 거부합니다.
정답
9. 데이터베이스에 정의된 모든 제약조건을 확인하세요.
데이터베이스에 정의된 모든 제약조건을 확인하세요.
힌트 1: sqlite_master 테이블에서 type = 'table'인 DDL을 조회하면 CHECK/NOT NULL 등을 볼 수 있고, type = 'index'에서 UNIQUE 인덱스를 확인.
정답
-- CHECK 제약조건이 포함된 테이블 DDL 확인
SELECT name, sql FROM sqlite_master
WHERE type = 'table'
AND sql LIKE '%CHECK%'
ORDER BY name;
실행 결과 (6행)
| name | sql |
|---|---|
| coupons | CREATE TABLE coupons ( |
| id ... | |
| customers | CREATE TABLE customers ( |
| id ... | |
| order_items | CREATE TABLE order_items ( |
| id ... | |
| payments | CREATE TABLE payments ( |
| id ... | |
| products | CREATE TABLE products ( |
| id ... | |
| reviews | CREATE TABLE reviews ( |
| id ... |
10. 중복 발생 시 에러 대신 업데이트하는 UPSERT를 실습하세요.
중복 발생 시 에러 대신 업데이트하는 UPSERT를 실습하세요.
힌트 1: INSERT OR IGNORE는 중복 시 무시, INSERT ... ON CONFLICT(id) DO UPDATE SET ...는 중복 시 기존 행을 업데이트.
정답
-- 위시리스트: 이미 있으면 무시
INSERT OR IGNORE INTO wishlists (customer_id, product_id, created_at)
VALUES (1, 1, '2025-06-01');
-- 상품: 이미 있으면 가격 업데이트
INSERT INTO products (id, category_id, supplier_id, name, sku, brand, price, cost_price, stock_qty, is_active, created_at, updated_at)
VALUES (1, 2, 1, '업데이트 테스트', 'SKU-0001', 'Test', 999999, 50, 10, 1, '2025-01-01', '2025-01-01')
ON CONFLICT(id) DO UPDATE SET
price = excluded.price,
updated_at = excluded.updated_at;
-- 변경 확인
SELECT id, name, price FROM products WHERE id = 1;