ENUM - 단일 선택 타입
ENUM은 열에 할당할 수 있는 값의 리스트를 정의하고, 이 리스트 중 하나만 선택하는 단일 선택만이 가능한 타입입니다.
내부 저장 방식
값들은 내부적으로 숫자로 저장되지만, 사용자에게는 문자열로 표시됩니다.
-- ENUM 정의 예시
CREATE TABLE products (
id INT PRIMARY KEY,
name VARCHAR(100),
status ENUM('active', 'inactive', 'pending')
);
-- 내부 매핑:
-- 'active' → 1
-- 'inactive' → 2
-- 'pending' → 3
-- (0은 빈 값 또는 잘못된 값에 할당됨)
기본 사용법
-- 정상적인 삽입
INSERT INTO products (name, status) VALUES
('상품A', 'active'),
('상품B', 'inactive'),
('상품C', 'pending');
-- 에러 발생하는 경우
INSERT INTO products (name, status) VALUES
('상품D', 'deleted'); -- Error: 정의되지 않은 값
-- 숫자로 직접 삽입 가능 (권장하지 않음)
INSERT INTO products (name, status) VALUES
('상품E', 1); -- 'active'와 동일
조회 및 정렬
-- 문자열로 조회
SELECT * FROM products WHERE status = 'active';
-- 내부 숫자값으로 정렬 (정의 순서대로)
SELECT * FROM products ORDER BY status;
-- 결과: active(1) → inactive(2) → pending(3) 순서
-- ENUM 값의 숫자 확인
SELECT name, status, status+0 AS status_number
FROM products;
SET - 다중 선택 타입
SET은 ENUM과 비슷하지만, 하나의 열에 여러 값을 저장할 수 있다는 점이 다르며, 비트 단위 연산을 할 수 있고 한 번에 여러 개의 조합으로 선택이 가능합니다.
내부 저장 방식과 제한
- 64개의 요소를 넣을 수 있음
- 비트마스크로 내부 저장
- 각 요소는 2의 거듭제곱 값을 가짐
다중 값 저장
-- 여러 값 동시 저장
INSERT INTO users (name, skills) VALUES
('개발자A', 'Java,Python'), -- 1 + 2 = 3
('개발자B', 'JavaScript,C#,Go'), -- 4 + 8 + 16 = 28
('개발자C', 'Python,JavaScript,Rust'); -- 2 + 4 + 32 = 38
-- 단일 값도 가능
INSERT INTO users (name, skills) VALUES
('개발자D', 'Java'); -- 1
-- 빈 값도 가능
INSERT INTO users (name, skills) VALUES
('개발자E', ''); -- 0
SET 조회 및 비트 연산
-- 특정 스킬을 가진 사용자 찾기
SELECT * FROM users WHERE FIND_IN_SET('Python', skills);
-- 여러 스킬 중 하나라도 가진 사용자
SELECT * FROM users WHERE skills & 3; -- Java(1) 또는 Python(2)
-- 특정 스킬 조합을 모두 가진 사용자
SELECT * FROM users WHERE (skills & 6) = 6; -- Python(2) AND JavaScript(4)
-- 비트 연산 예시
SELECT name, skills, skills+0 AS skills_number
FROM users;
-- 개발자A: Java,Python → 3
-- 개발자B: JavaScript,C#,Go → 28
ENUM vs SET
| 특성 | ENUM | SET |
| 선택 개수 | 단일 선택 | 다중 선택 |
| 최대 요소 | 65,535개 | 64개 |
| 저장 방식 | 순서 번호 | 비트마스크 |
| 연산 | 순서 비교 | 비트 연산 |
-- ENUM 사용 사례: 상태, 등급, 카테고리
CREATE TABLE orders (
id INT PRIMARY KEY,
status ENUM('pending', 'processing', 'shipped', 'delivered', 'cancelled'),
priority ENUM('low', 'medium', 'high', 'urgent')
);
-- SET 사용 사례: 권한, 태그, 다중 선택 옵션
CREATE TABLE user_permissions (
user_id INT PRIMARY KEY,
permissions SET('read', 'write', 'delete', 'admin', 'moderator')
);
CREATE TABLE articles (
id INT PRIMARY KEY,
title VARCHAR(200),
tags SET('tech', 'programming', 'database', 'web', 'mobile', 'ai')
);
장점
- 공간적 이점
- ENUM의 공간 효율성
-- 일반적인 VARCHAR 방식
CREATE TABLE products_varchar (
status VARCHAR(20) -- 'active', 'inactive', 'pending'
);
-- 각 행마다 최대 20바이트 사용
-- ENUM 방식
CREATE TABLE products_enum (
status ENUM('active', 'inactive', 'pending')
);
-- 각 행마다 1바이트만 사용 (3개 값이므로)
-- 공간 절약: 95% 감소 (20바이트 → 1바이트)
- SET의 공간 효율성
-- 일반적인 별도 테이블 방식
CREATE TABLE user_skills_normalized (
user_id INT,
skill VARCHAR(50),
PRIMARY KEY(user_id, skill)
);
-- 스킬 하나당 54바이트 (INT 4 + VARCHAR 50)
-- SET 방식
CREATE TABLE users_set (
id INT,
skills SET('Java', 'Python', 'JavaScript', 'C#', 'Go', 'Rust')
);
-- 최대 8바이트로 64개 스킬 표현 가능
단점
- 스키마 수정의 복잡성
-- 새로운 값 추가가 필요한 경우
-- 기존 ENUM: ('active', 'inactive', 'pending')
-- 새 상태 'archived' 추가하려면 ALTER 필요
ALTER TABLE products
MODIFY COLUMN status ENUM('active', 'inactive', 'pending', 'archived');
-- 문제점:
-- 1. 테이블 잠금 발생 (대용량 테이블에서 위험)
-- 2. 애플리케이션 코드와 DB 스키마 동기화 필요
-- 3. 배포 시 순서 의존성 발생
- 애플리케이션 수정에 따른 데이터베이스 변경
// C# 애플리케이션 코드 예시
public enum ProductStatus
{
Active,
Inactive,
Pending,
Archived // 새로 추가된 상태
}
// 새 enum 값 추가 시:
// 1. C# 코드 수정
// 2. 데이터베이스 스키마 수정 필요
// 3. 기존 데이터 마이그레이션 고려
// 4. 배포 순서 조정 필요
- 이식성 문제
-- MySQL ENUM/SET은 표준 SQL이 아님
-- PostgreSQL 등 다른 DB로 이전 시 문제 발생
-- 대안: CHECK 제약조건 (표준 SQL)
CREATE TABLE products (
id INT PRIMARY KEY,
status VARCHAR(20) CHECK (status IN ('active', 'inactive', 'pending'))
);
'ZeroBase > CS' 카테고리의 다른 글
| ERD(Entity Relation Diagram) (3) | 2025.09.21 |
|---|---|
| 데이터베이스 관계와 키(Key) (1) | 2025.09.16 |
| 힙(Heap) (0) | 2025.09.15 |
| 해시테이블(HashTable) (0) | 2025.09.13 |
| Map과 Set (0) | 2025.09.13 |