기본 문법
CREATE TABLE users (
id INT,
name VARCHAR(50),
age INT
);
users 라는 테이블을 생성합니다.
테이블 내에는 id, name, age 의 정보가 들어갑니다.
id 는 정수형(INT)
name 은 문자열(최대 50글자)
age 는 정수형(INT)
| 자료형 | 의미 | 예 |
| INT | 정수 (-2,147,483,648 ~ 2,147,483,647) |
123 |
| TINYINT | 아주 작은 정수 (-128 ~ 127) |
1 (주로 boolean 대용) |
| BIGINT | 큰 정수 (-9,223,372,036,854,775,808 ~ 9,223,372,036,854,775,807) |
9999999999 |
| UNSIGNED | 음수 금지 (0 이상만 저장 가능) |
UNSIGNED INT 0 ~ 4,294,967,295 |
| VARCHAR(n) | 가변 길이 문자열 (최대 n자) | 'power' |
| CHAR(n) | 고정 길이 문자열 (n자 고정, 부족하면 공백으로 채움) |
'A' (CHAR(1)) |
| TEXT | 긴 문자열 (최대 65,535자) |
'긴 설명입니다...' |
| DATE | 날짜 (YYYY-MM-DD) |
'2025-07-11' |
| TIME | 시간 (HH:MM:SS) |
'13:45:00' |
| DATETIME | 날짜 + 시간 (YYYY-MM-DD HH:MM:SS) |
'2025-07-11 18:00:00' |
| TIMESTAMP | 날짜 + 시간 (UTC 기준, 자동 기록/갱신 가능) |
'2025-07-11 18:00:00' |
| YEAR | 연도 (YYYY) |
'2025' |
| FLOAT, DOUBLE | 실수 (소수점 숫자, DOUBLE은 더 정밀) |
3.14 |
| BOOLEAN(= TINYINT(1)) | 참/거짓 (0 = 거짓, 1 = 참) | TRUE, FALSE |
| ENUM | 제한된 값만 허용 (목록 중 선택) |
'남자', '여자' |
| JSON | 구조화된 데이터 (키-값 형태) |
'{"name":"홍길동","age":25}' |
기본 제약조건 (Constraints)
CREATE TABLE users (
id INT PRIMARY KEY, -- 고유 식별자
name VARCHAR(50) NOT NULL,-- 반드시 입력해야 함
age INT DEFAULT 0 -- 값이 없으면 기본값 0
);
id 는 회원 번호처럼 절대 겹치면 안 되는 값
name 은 꼭 필요함. NULL 은 안됨
age 는 입력 안 하면 0으로 입력됨.
| 제약조건 | 의미 |
| PRIMARY KEY | 기본 키(유일값 + NULL 불가) |
| NOT NULL | 빈 값 금지 |
| DEFAULT | 값이 없으면 기본값 자동 입력 |
| UNIQUE | 중복 불가 |
| CHECK | 조건 만족 강제 |
| FOREIGN KEY | 참조 무결성 |
AUTO_INCREMENT
등록된 순번으로 1, 2, 3..... 자동으로 증가해야 하는 경우가 있다.
CREATE TABLE users (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(50) NOT NULL,
age INT DEFAULT 0
);
id 는 새로운 데이터가 들어올 때마다 자동으로 +1 이 된다.
외래 키 (Foreign Key)
회원이 공연 티켓을 구매할 때,
회원 테이블(users) 과 구매 테이블(ticket) 을 연결해야 한다.
CREATE TABLE tickets (
ticket_id INT AUTO_INCREMENT PRIMARY KEY,
user_id INT,
show_name VARCHAR(100),
FOREIGN KEY (user_id) REFERENCES users(id)
);
user_id 는 users 테이블의 id 를 참조한다. (곧, user_id == users.id)
즉, users 에 있는 회원만이 티켓을 살 수 있음
+ 심화
CREATE TABLE [IF NOT EXISTS] 스키마명.테이블명 (
컬럼명 데이터타입 [NULL|NOT NULL] [DEFAULT 값] [AUTO_INCREMENT]
, ...
, [CONSTRAINT 제약이름] PRIMARY KEY (컬럼[, ...])
, [CONSTRAINT 제약이름] UNIQUE KEY (컬럼[, ...])
, [CONSTRAINT 제약이름] FOREIGN KEY (컬럼[, ...])
REFERENCES 참조테이블(컬럼[, ...])
[ON UPDATE {RESTRICT|CASCADE|SET NULL|NO ACTION}]
[ON DELETE {RESTRICT|CASCADE|SET NULL|NO ACTION}]
, [INDEX/KEY 인덱스이름 (컬럼[, ...])]
)
ENGINE=InnoDB
DEFAULT CHARSET=utf8mb4
[COLLATE=utf8mb4_general_ci]
[COMMENT='테이블 설명'];
IF NOT EXISTS : 같은 이름의 테이블이 이미 있으면 통과
ENGINE=InnnoDB : 트랜잭션 / 외래키 지원.
CHARSET / COLLATE : 한글 / 이모지까지 안전한 utf9mb4 권장.
COMMENT : 스키마를 문서화 (팀 협업 필수)
인덱스 기본기
필요할 때만 만든다 (과도하면 쓰기 성능 / 공간 낭비)
PK / UNIQUE 는 자동 인덱스 생성
INDEX (col1, col2) 복합 인덱스 : 선두 컬럼 기준으로만 잘 탄다.
FULLTEXT : 자연어 검색 (name, details 등)
Prefix Index : 긴 문자열 앞부분만 인덱싱
외래키 와 참조 무결성
이력 보존이 중요하면 삭제 대신 소프트 삭제 (deleted_at) 권장
REFERENCES 로 부모/자식 테이블 연결
ON DELETE / ON UPDATE 정책 :
RESTRICT / NO ACTION:차단 (사실상 동일)
CASCADE : 부모 변경 / 삭제를 자식에 전파
SET NULL : 부모 삭제 시 자식을 NULL 로
테이블 옵션
ENGINE=InnoDB : 기본
DEFAULT CHARSET=utf8mb4, COLLATE=utf8mb4_general_ci
ROW_FORMAT, TABLESPACE 등은 특수한 경우에만
자주 쓰는 변형 문법
임시 테이블
CREATE TEMPORARY TABLE temp_result (...);
다른 테이블과 동일한 구조
CREATE TABLE new_like_old LIKE old;
조회 결과로 테이블 만들기
CREATE TABLE copy AS
SELECT * FROM original WHERE created_at >= CURDATE();
심화 기능 모음
생성(가상) 컬럼
age INT
GENERATED ALWAYS AS (YEAR(CURDATE()) - CAST(birthyear AS UNSIGNED))
VIRTUAL;
CHECK 제약
price INT UNSIGNED NOT NULL,
CHECK (price > 0);
JSON 컬럼과 검증
extra JSON NOT NULL,
CHECK (JSON_VALID(extra));
FULLTEXT (한국어면 ngram 파서 고려)
FULLTEXT KEY ft_perf (name, details) WITH PARSER ngram;
파티셔닝(대용량)
PARTITION BY RANGE (YEAR(created_at)) (
PARTITION p2024 VALUES LESS THAN (2025),
PARTITION p2025 VALUES LESS THAN (2026),
PARTITION pmax VALUES LESS THAN MAXVALUE
);
Invisible Column (8.0.13+)
internal_note VARCHAR(255) INVISIBLE
예제
더보기
-- =========================================
-- 회원 테이블
-- =========================================
CREATE TABLE users (
num INT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '등록 순번',
user_id VARCHAR(50) NOT NULL COMMENT '유저 아이디',
password VARCHAR(255) NOT NULL COMMENT '비밀번호(해시 저장)',
name VARCHAR(50) NOT NULL COMMENT '이름',
birthyear YEAR NOT NULL COMMENT '출생년',
gender ENUM('M', 'F', 'O') NOT NULL COMMENT '성별(M: 남, F: 여, O: 기타)',
email VARCHAR(100) DEFAULT NULL COMMENT '이메일',
phone VARCHAR(20) DEFAULT NULL COMMENT '연락처',
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '계정 생성 시간',
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '마지막 수정 시간',
PRIMARY KEY (user_id),
UNIQUE KEY uq_user_num (num),
UNIQUE KEY uq_email (email)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='유저 정보 테이블';
-- =========================================
-- 관리자 테이블
-- =========================================
CREATE TABLE admins (
num INT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '등록 순번',
admin_id VARCHAR(50) NOT NULL COMMENT '관리자 아이디',
password VARCHAR(255) NOT NULL COMMENT '비밀번호(해시 저장)',
role_level TINYINT UNSIGNED NOT NULL DEFAULT 1 COMMENT '권한 등급(1: 일반, 9: 최고관리자)',
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '계정 생성 시간',
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '마지막 수정 시간',
PRIMARY KEY (admin_id),
UNIQUE KEY uq_admin_num (num)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='관리자 정보 테이블';
-- =========================================
-- 공연 정보 테이블
-- =========================================
CREATE TABLE performances (
performance_id INT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '공연 ID',
category ENUM('콘서트', '뮤지컬', '연극', '클래식', '무용', '전시', '행사') NOT NULL COMMENT '공연 분류',
name VARCHAR(100) NOT NULL COMMENT '공연 이름',
event_datetime DATETIME NOT NULL COMMENT '공연 일시',
location VARCHAR(255) NOT NULL COMMENT '공연 장소',
total_seats INT UNSIGNED NOT NULL COMMENT '총 좌석 수',
price INT UNSIGNED NOT NULL COMMENT '티켓 가격(원화 단위)',
rating ENUM('전체관람가', '7세 이상', '12세 이상', '15세 이상', '18세 이상') NOT NULL COMMENT '관람 등급',
details TEXT DEFAULT NULL COMMENT '상세 정보',
image_url VARCHAR(255) DEFAULT NULL COMMENT '공연 사진 URL',
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '등록일',
created_by VARCHAR(50) NOT NULL COMMENT '등록자(관리자 ID)',
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '마지막 수정일',
PRIMARY KEY (performance_id),
FOREIGN KEY (created_by) REFERENCES admins(admin_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='공연 정보 테이블';
-- =========================================
-- 티켓 구매 테이블
-- =========================================
CREATE TABLE ticket_purchases (
ticket_id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '티켓 ID',
user_id VARCHAR(50) NOT NULL COMMENT '구매자 ID(회원 테이블 FK)',
user_name VARCHAR(50) NOT NULL COMMENT '구매자 이름',
birthyear YEAR NOT NULL COMMENT '구매자 출생년도',
gender ENUM('M', 'F', 'O') NOT NULL COMMENT '구매자 성별(스냅샷)',
image_url VARCHAR(255) DEFAULT NULL COMMENT '유저 사진 URL',
performance_id INT UNSIGNED NOT NULL COMMENT '공연 ID(공연 정보 FK)',
performance_name VARCHAR(100) NOT NULL COMMENT '공연 이름',
event_datetime DATETIME NOT NULL COMMENT '공연 일시',
location VARCHAR(255) NOT NULL COMMENT '공연 장소',
seat_number VARCHAR(10) DEFAULT NULL COMMENT '좌석 번호',
qr_code VARCHAR(255) NOT NULL COMMENT 'QR 코드 URL',
status ENUM('구매완료', '취소', '환불완료', '사용완료') NOT NULL DEFAULT '구매완료' COMMENT '티켓 상태',
cancelled_at DATETIME DEFAULT NULL COMMENT '취소/환불 일시',
cancel_reason VARCHAR(255) DEFAULT NULL COMMENT '취소/환불 사유',
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '구매일시',
PRIMARY KEY (ticket_id),
FOREIGN KEY (user_id) REFERENCES users(user_id),
FOREIGN KEY (performance_id) REFERENCES performances(performance_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='티켓 구매 테이블';
-- =========================================
-- 티켓 검증 테이블
-- =========================================
CREATE TABLE ticket_validations (
validation_id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '검증 ID',
admin_id VARCHAR(50) NOT NULL COMMENT '검증한 관리자 ID(관리자 테이블 FK)',
user_id VARCHAR(50) NOT NULL COMMENT '구매자 ID(회원 테이블 FK)',
performance_id INT UNSIGNED NOT NULL COMMENT '공연 ID(공연 테이블 FK)',
ticket_id BIGINT UNSIGNED NOT NULL COMMENT '티켓 ID(티켓 구매 테이블 FK)',
status ENUM('승인', '거부') NOT NULL COMMENT '검증 결과',
reason VARCHAR(255) DEFAULT NULL COMMENT '거부 사유(선택)',
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '검증 일시',
PRIMARY KEY (validation_id),
FOREIGN KEY (user_id) REFERENCES users(user_id),
FOREIGN KEY (admin_id) REFERENCES admins(admin_id),
FOREIGN KEY (performance_id) REFERENCES performances(performance_id),
FOREIGN KEY (ticket_id) REFERENCES ticket_purchases(ticket_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='티켓 검증 테이블';
'MySQL' 카테고리의 다른 글
| MySQL - JOIN (1) | 2025.08.25 |
|---|---|
| SELECT 문 (5) | 2025.08.25 |
| MySQL C API 주요 함수 (1) | 2025.07.10 |