๐๏ธBoard ์คํค๋ง ์์ฑ
CREATE DATABASE Board;
USE Board
๐๏ธ์ฌ์ฉ์ ํ ์ด๋ธ ์์ฑ
CREATE TABLE users (
-> id INT NOT NULL AUTO_INCREMENT, // PRIMARY KEY ์ถ๊ฐ
-> name VARCHAR(30) NOT NULL,
-> job VARCHAR(100),
-> birth DATE
-> );
โ์ค๋ฅ: Incorrect table definition
Incorrect table definition; there can be only one auto column and it must be defined as a key
AUTO_INCREMENT ์์ฑ์ ๊ฐ์ง ์ปฌ๋ผ์ด ํ๋ ์ด์์ด๊ฑฐ๋, PRIMARY KEY ๋๋ UNIQUE KEY๋ก ์ค์ ๋์ง ์์ ์ปฌ๋ผ์ AUTO_INCREMENT๋ฅผ ๋ถ์์ ๋ ๋ฐ์ํ๋ MySQL ์ค๋ฅ์ด๋ค.
id ์ปฌ๋ผ์ด AUTO_INCREMENT์ธ๋ฐ, PRIMARY KEY ๋๋ UNIQUE ์ ์ฝ ์กฐ๊ฑด์ด ์๊ธฐ ๋๋ฌธ์ ๋ฐ์ํ์๋ค. id ์ปฌ๋ผ์ PRIMARY KEY๋ฅผ ๋ถ์ฌํ์ฌ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ์๋ค.
AUTO_INCREMENT
AUTO_INCREMENT๋ ์ ๋ ์ฝ๋๊ฐ ์ฝ์ ๋ ๋๋ง๋ค ์๋์ผ๋ก ์ซ์๋ฅผ ์ฆ๊ฐ์์ผ ๊ณ ์ ํ ๊ฐ์ ์์ฑํ๋ MySQL์ ์์ฑ
โ ์ฌ์ฉ ์กฐ๊ฑด:
AUTO_INCREMENT๋ INT ๊ณ์ด ์ซ์ ํ์ ์์๋ง ์ฌ์ฉ ๊ฐ๋ฅ (e.g., INT, BIGINT, SMALLINT)- ๋ฐ๋์
PRIMARY KEY๋๋UNIQUE์ ์ฝ ์กฐ๊ฑด์ด ์์ด์ผ ํ๋ค. - ํ๋์ ํ ์ด๋ธ์ ๋ฑ ํ๋๋ง ์กด์ฌํ ์ ์๋ค.
CREATE TABLE users (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(100)
);
INSERT INTO users (name) VALUES ('Alice');
INSERT INTO users (name) VALUES ('Bob');
| id | name |
|---|---|
| 1 | Alice |
| 2 | Bob |
์๋์ฒ๋ผ ์์๊ฐ์ ์ค์ ํด ์ค ์ ์๋ค.
ALTER TABLE users AUTO_INCREMENT = 100;
๐ก์ฌ์ฉ ์ ์ฃผ์์ฌํญ:
- ์ค๊ฐ ๊ฐ์ด ์ญ์ ๋์ด๋, ์๋ ์ฆ๊ฐ ๊ฐ์ ๋๋์๊ฐ์ง ์๋๋ค.
- ์ซ์ ์ฌ์ฌ์ฉ์ ์ํ๋ฉด ์๋์ผ๋ก ๊ด๋ฆฌํ๊ฑฐ๋ TRUNCATE๋ก ์ ์ฒด ์ด๊ธฐํ ํ์ํ๋ค.
DESC
MySQL์์ ํ ์ด๋ธ์ ๊ตฌ์กฐ(์คํค๋ง)๋ฅผ ํ์ธํ ๋ ์ฌ์ฉํ๋ ๋ช ๋ น์ด
DESC๋ฅผ ์ฌ์ฉํ์ฌ ์์ฑ๋ ํ ์ด๋ธ ๊ตฌ์กฐ๋ฅผ ํ์ธํ ์ ์๋ค.
DESC users

์ ์ฝ ์กฐ๊ฑด
์ ์ฝ ์กฐ๊ฑด(Constraints)์ ํ ์ด๋ธ์ ์ ์ฅ๋๋ ๋ฐ์ดํฐ์ ๋ฌด๊ฒฐ์ฑ(์ ํ์ฑ + ์ผ๊ด์ฑ)์ ๋ณด์ฅํ๊ธฐ ์ํ ๊ท์น
| PRIMARY KEY | ๊ฐ ํ์ ๊ณ ์ ํ๊ฒ ์๋ณ. NULL ํ์ฉ โ | id INT PRIMARY KEY |
| UNIQUE | ๊ณ ์ ํ ๊ฐ๋ง ํ์ฉ. ์ค๋ณต โ, NULL โ | email VARCHAR(100) UNIQUE |
| NOT NULL | NULL ์ ๋ ฅ โ | name VARCHAR(50) NOT NULL |
| DEFAULT | ๊ฐ์ด ์์ ๋ ์๋์ผ๋ก ์ค์ ๋ ๊ธฐ๋ณธ๊ฐ | created_at DATETIME DEFAULT NOW() |
| CHECK | ์กฐ๊ฑด ๋ง์กฑ ์๋ง ์ฝ์ ํ์ฉ | age INT CHECK (age >= 0) |
| FOREIGN KEY | ๋ค๋ฅธ ํ ์ด๋ธ์ ํค๋ฅผ ์ฐธ์กฐ (๊ด๊ณ ์ค์ ) | user_id INT, FOREIGN KEY (user_id) REFERENCES users(id) |
๐๏ธ์ฌ์ฉ์ ํ ์ด๋ธ ๋ฐ์ดํฐ ์ฝ์
INSERT INTO users(name, job, birth) VALUES("gongu", "actor", "800123");

๐๏ธ๊ฒ์๊ธ ํ ์ด๋ธ ์์ฑ
CREATE TABLE posts (
-> id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
-> title VARCHAR(100) NOT NULL,
-> content VARCHAR(2000),
-> created_at TIMESTAMP DEFAULT NOW(),
-> updated_at TIMESTAMP DEFAULT NOW()
-> );
MySQL ๋ ์ง/์๊ฐ ํ์
DATE: ๋ ์ง๋ง ์ ์ฅ(yyyy-mm-dd)
DATETIME: ๋ ์ง + ์๊ฐ(yyyy-mm-dd hh:mm:ss)
TIME: ์๊ฐ๋ง(hh:mm:ss)
TIMESTAMP: ์์คํ ์๊ฐ๋ ์ ๋ณด์ ๋ง๊ฒ ์ผ์๋ฅผ ์ ์ฅ(yyyy-mm-dd hh-mm-ss)
TIMESTMAP
TIMESTAMP๋ MySQL์์ ์์คํ ์๊ฐ๋๋ฅผ ๊ธฐ์ค์ผ๋ก ์ ์ฅ๋๋ฉฐ, ๋ด๋ถ์ ์ผ๋ก๋ UTC๋ก ๋ณํ๋์ด ๋ณด๊ด๋๋ ํน๋ณํ ํ์
๐งญ TIMESTAMP์ ์๊ฐ ์ฒ๋ฆฌ ๋ฐฉ์
1. ์ ์ฅ ์: ๋ก์ปฌ ์๊ฐ → UTC๋ก ๋ณํ
MySQL ์๋ฒ์ ์์คํ
์๊ฐ๋๋ฅผ ๊ธฐ์ค์ผ๋ก ์
๋ ฅํ ๊ฐ์ ์๋์ผ๋ก UTC๋ก ๋ณํ๋์ด ์ ์ฅ๋๋ค.
์์ (์๋ฒ๊ฐ KST = UTC+9์ผ ๊ฒฝ์ฐ):
INSERT INTO logs (created_at) VALUES ('2025-05-02 12:00:00');
- ์ ๋ ฅ๊ฐ: 2025-05-02 12:00:00 (KST)
- ์ค์ ์ ์ฅ๋๋ ๊ฐ: 2025-05-02 03:00:00 (UTC)
2. ์กฐํ ์: UTC → ๋ก์ปฌ ์๊ฐ๋๋ก ๋ณํ๋์ด ์ถ๋ ฅ
์ ์ฅ๋ UTC ๊ฐ์ ํ์ฌ ์ธ์
์ ์๊ฐ๋(time_zone)์ ๋ฐ๋ผ ๋ก์ปฌ ์๊ฐ์ผ๋ก ๋ณํ๋์ด ๋ณด์ฌ์ง๋ค.
→ ์ฌ์ฉ์ ์ ์ฅ์์ ๋ก์ปฌ ์๊ฐ์ผ๋ก ์ ๋ ฅํ๊ณ ๋ก์ปฌ ์๊ฐ์ผ๋ก ๋ณธ ๊ฒ์ฒ๋ผ ๋ณด์ธ๋ค.
| DATETIME | TIMESTAMP | |
| ์ ์ฅ ๋ฐฉ์ | ์ ๋ ฅ๋ ๊ทธ๋๋ก ์ ์ฅ | ๋ด๋ถ์ ์ผ๋ก UTC๋ก ์ ์ฅ |
| ์๊ฐ๋ ์ํฅ | ์์ | ์์ (๋ณํ๋จ) |
| ๊ถ์ฅ ์ฌ์ฉ | ์ ๋ ์๊ฐ ๊ธฐ๋ก (์์ผ, ์์ฝ์ผ ๋ฑ) | ๋ณํํ๋ ์์ ๊ธฐ๋ก (๋ก๊ทธ, ์์ฑ์ผ ๋ฑ) |
| ํํ ๋ฒ์ | 1000-01-01 ~ 9999-12-31 | 1970-01-01 ~ 2038-01-19 |
DEFAULT vs NOT NULL
DEFAULT์ NOT NULL์ ์ด์ ์ ์ฝ์กฐ๊ฑด(Constraints) ์ค ๊ธฐ๋ณธ๊ฐ๊ณผ null ํ์ฉ ์ฌ๋ถ๋ฅผ ์ ์ดํ๋ ํต์ฌ ์ต์
โ NOT NULL
- ํด๋น ์ปฌ๋ผ์ NULL ๊ฐ์ ํ์ฉํ์ง ์๋๋ค.
- ๋ฐ์ดํฐ๋ฅผ ์ฝ์ ํ ๋ ๋ฐ๋์ ๊ฐ์ด ์์ด์ผ ํ๋ค.
- ๋๋ฝ๋ ๊ฐ์ ํ์ฉํ์ง ์๋๋ก ํ์ฌ ๋ฐ์ดํฐ ๋ฌด๊ฒฐ์ฑ(data integrity)์ ๋ณด์ฅํ๋ค.
โ DEFAULT
- ๊ฐ์ ์ง์ ํ์ง ์์์ ๋ ์๋์ผ๋ก ์ฑ์์ง๋ ๊ธฐ๋ณธ๊ฐ
- INSERT ์ ํด๋น ์ปฌ๋ผ์ ์๋ตํ๋ฉด ์ด ๊ฐ์ผ๋ก ์๋ ์ ๋ ฅ๋๋ค.
- NULL์ ํ์ฉํ ์๋ ์๊ณ ์ ํ ์๋ ์๋ค. (→ NOT NULL๊ณผ ํจ๊ป ์ฐ๋ฉด ๋ช ํํจ)
โญ NOT NULL์ NULL ์ ๋ ฅ์ ๊ฐ์ ๋ก ๋ง๋ ์ ์ฝ ์กฐ๊ฑด์ด๊ธฐ ๋๋ฌธ์, ๋์ ๋ณํํด ์ฐ๋ฉด ๋์ฑ ์์ ์ ์ธ ๋ฐ์ดํฐ ๊ด๋ฆฌ ๊ฐ๋ฅ!
CREATE TABLE posts (
id INT PRIMARY KEY AUTO_INCREMENT,
title VARCHAR(100) NOT NULL,
views INT NOT NULL DEFAULT 0
);
๐๏ธ๊ฒ์๊ธ ํ ์ด๋ธ ์ฝ์ , ์ปฌ๋ผ ์ถ๊ฐ, ์์
๊ฒ์๊ธ ํ ์ด๋ธ์ ๋ฐ์ดํฐ ์ฝ์
INSERT INTO posts(title, content) VALUES ("title1", "content");
๊ฒ์๊ธ ํ ์ด๋ธ์ ์์ ์ผ์ ์ปฌ๋ผ ์ถ๊ฐ
ALTER TABLE posts MODIFY COLUMN updated_at DATETIME DEFAULT NOW() ON UPDATE NOW();
๊ฒ์๊ธ ํ ์ด๋ธ id=2 ์์
UPDATE posts SET content = "updated!" WHERE id = 2;
ALTER
์ด๋ฏธ ์กด์ฌํ๋ ํ ์ด๋ธ์ ๊ตฌ์กฐ๋ฅผ ์์ ํ ๋ ์ฌ์ฉํ๋ SQL ๋ช ๋ น์ด
ALTER TABLE ํ ์ด๋ธ๋ช ์์ ๋ด์ฉ;
ํ์์ผ๋ก ์ฌ์ฉํ๋ค.
ALTER TABLE posts
ADD COLUMN updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP;
- MySQL์์ ๋ ์ฝ๋๊ฐ ์ ๋ฐ์ดํธ๋ ๋ ์๋์ผ๋ก ์๊ฐ ๊ฐฑ์ ํ๋๋ก updated_at ์ปฌ๋ผ์ ์์ ํ๋ค.
| ์ปฌ๋ผ ์ถ๊ฐ | ALTER TABLE posts ADD COLUMN views INT DEFAULT 0; |
| ์ปฌ๋ผ ์ญ์ | ALTER TABLE posts DROP COLUMN views; |
| ์ปฌ๋ผ ์ด๋ฆ ๋ณ๊ฒฝ (MySQL 8+) | ALTER TABLE posts RENAME COLUMN old_name TO new_name; |
| ์ปฌ๋ผ ์๋ฃํ ๋ณ๊ฒฝ | ALTER TABLE posts MODIFY COLUMN title VARCHAR(200); |
| ๊ธฐ๋ณธ๊ฐ ๋ณ๊ฒฝ | ALTER TABLE posts ALTER COLUMN views SET DEFAULT 100; |
| ์ ์ฝ์กฐ๊ฑด ์ถ๊ฐ | ALTER TABLE posts ADD CONSTRAINT ... |
| ํ ์ด๋ธ ์ด๋ฆ ๋ณ๊ฒฝ | RENAME TABLE old_name TO new_name; |
๐๏ธ๊ฒ์๊ธ ํ ์ด๋ธ์ ์์ฑ์ ์ปฌ๋ผ FK ์ถ๊ฐ ๋ฐ ์ค์
ALTER TABLE posts
-> ADD COLUMN user_id INT;
ALTER TABLE posts
-> ADD FOREIGN KEY(user_id)
-> REFERENCES users(id);
Foreign Key
๋ ํ ์ด๋ธ ๊ฐ์ ๊ด๊ณ๋ฅผ ์ค์ ํ๋ ์ ์ฝ์กฐ๊ฑด
๋ฐ์ดํฐ๋ฒ ์ด์ค์์ ํ ์ด๋ธ ๊ฐ ์ฐ๊ด์ฑ์ ํํํ๊ณ , ๋ฐ์ดํฐ ๋ฌด๊ฒฐ์ฑ์ ๋ณด์ฅํ๋ ๋ฐ ์ฌ์ฉํ๋ค.
- ๋ค๋ฅธ ํ ์ด๋ธ์ ๊ธฐ๋ณธ ํค(primary key)๋ฅผ ์ฐธ์กฐํ๋ ์ด(column)์ด๋ค.
- ํ ํ ์ด๋ธ์ ํน์ ์ด ๊ฐ์ด ๋ค๋ฅธ ํ ์ด๋ธ์ ๋ฐ๋์ ์กด์ฌํด์ผ ํ๋ค๋ ์ ์ฝ์ ์ค์ ํ๋ค.
- ์ฃผ๋ก 1:N ๊ด๊ณ์์ ์ฌ์ฉ๋๋ค.

๐งฉ์กฐ์ธ
๋ ๊ฐ ์ด์์ ํ ์ด๋ธ์ ์ฐ๊ฒฐํ์ฌ ๋ฐ์ดํฐ๋ฅผ ํ๋์ ๊ฒฐ๊ณผ๋ก ๊ฒฐํฉํ๋ SQL ๋ช ๋ น์ด
SELECT * FROM posts LEFT
-> JOIN users ON posts.user_id = users.id;
์ฃผ๋ก ํ ์ด๋ธ ๊ฐ์ ๊ด๊ณ๋ฅผ ๋ฐํ์ผ๋ก ๋ฐ์ดํฐ๋ฅผ ๊ฒฐํฉํ๊ณ , ์ฌ๋ฌ ํ ์ด๋ธ์ ๋ถ์ฐ๋ ์ ๋ณด๋ฅผ ์กฐํฉํ์ฌ ์ ์ฉํ ๊ฒฐ๊ณผ๋ฅผ ์ป์ ๋ ์ฌ์ฉํ๋ค.
INNER JOIN
๋ ํ ์ด๋ธ์ ๊ณตํต๋ ๋ฐ์ดํฐ๊ฐ ์์ ๊ฒฝ์ฐ์๋ง ๊ทธ ๋ฐ์ดํฐ๋ฅผ ๊ฒฐํฉํ์ฌ ๋ฐํํ๋ค. ๊ณตํต๋ ๋ฐ์ดํฐ๊ฐ ์๋ ๊ฒฝ์ฐ, ๊ฒฐ๊ณผ์ ํฌํจ๋์ง ์๋๋ค.
SELECT * FROM A INNER JOIN B ON A.id = B.a_id;
OUTER JOIN
LEFT JOIN
์ผ์ชฝ ํ
์ด๋ธ(LEFT)์ ๋ชจ๋ ๋ฐ์ดํฐ๋ฅผ ํฌํจํ๊ณ , ์ค๋ฅธ์ชฝ ํ
์ด๋ธ(RIGHT)์์ ์ผ์นํ๋ ๊ฐ์ด ์์ ๊ฒฝ์ฐ ๊ทธ ๊ฐ์ ๊ฒฐํฉํ๋ค. ์ผ์นํ๋ ๋ฐ์ดํฐ๊ฐ ์๋ ๊ฒฝ์ฐ, ์ค๋ฅธ์ชฝ ํ
์ด๋ธ์ ์ปฌ๋ผ์ NULL๋ก ๋ฐํ๋๋ค.
SELECT * FROM A LEFT JOIN B ON A.id = B.a_id;
RIGHT JOIN
์ค๋ฅธ์ชฝ ํ
์ด๋ธ(RIGHT)์ ๋ชจ๋ ๋ฐ์ดํฐ๋ฅผ ํฌํจํ๊ณ , ์ผ์ชฝ ํ
์ด๋ธ(LEFT)์์ ์ผ์นํ๋ ๊ฐ์ด ์์ ๊ฒฝ์ฐ ๊ทธ ๊ฐ์ ๊ฒฐํฉํ๋ค. ์ผ์นํ๋ ๋ฐ์ดํฐ๊ฐ ์๋ ๊ฒฝ์ฐ, ์ผ์ชฝ ํ
์ด๋ธ์ ์ปฌ๋ผ์ NULL๋ก ๋ฐํ๋๋ค.
SELECT * FROM A RIGHT JOIN B ON A.id = B.a_id;
FULL JOIN
LEFT JOIN๊ณผ RIGHT JOIN์ ๊ฒฐํฉํ ๊ฒ์ผ๋ก, ๋ ํ
์ด๋ธ์ ๋ชจ๋ ๋ฐ์ดํฐ๋ฅผ ํฌํจํ๋ค. ๋ ํ
์ด๋ธ์์ ์ผ์นํ๋ ๋ฐ์ดํฐ๊ฐ ์์ ๊ฒฝ์ฐ ๊ฒฐํฉํ๊ณ , ์ผ์นํ์ง ์๋ ๊ฒฝ์ฐ์๋ NULL๋ก ์ฑ์ด๋ค.
-- MySQL์์๋ UNION ์ฌ์ฉ
SELECT * FROM A LEFT JOIN B ON A.id = B.a_id
UNION
SELECT * FROM A RIGHT JOIN B ON A.id = B.a_id;
๐กMySQL์์๋ FULL OUTER JOIN์ด ์ง์๋์ง ์์ง๋ง, ๋ค๋ฅธ DBMS์์๋ ์ง์๋๋ค. MySQL์์๋ ์ด๋ฅผ UNION์ผ๋ก ๋์ฒดํ ์ ์๋ค.
LEFT JOIN์ ์ฌ์ฉํ์ฌ, users์ posts ํ ์ด๋ธ ์กฐ์ธ์ ์ํํ ๊ฒฐ๊ณผ๋ ๋ค์๊ณผ ๊ฐ๋ค.

์ด๋ฒ ๊ธ์์๋ ์ฌ์ฉ์์ ๊ฒ์๊ธ์ด๋ผ๋ ์์ฃผ ๊ธฐ๋ณธ์ ์ธ ํ ์ด๋ธ ๊ตฌ์กฐ๋ฅผ ๋ค๋ค์ง๋ง, ๊ทธ ์์ ์จ์ ์ค๊ณ ํฌ์ธํธ์ ์ ์ฝ์กฐ๊ฑด๋ค์ด ์๊ฐ๋ณด๋ค ๋ง๋ค๋ ๊ฑธ ์์ผ ๋๊ผ๋ค. AUTO_INCREMENT, DEFAULT, NOT NULL, TIMESTAMP ๊ฐ์ ์์ฑ๋ค์ ์ด๋ฏธ ์ต์ํ๋ค๊ณ ์๊ฐํ์ง๋ง, ๊ณต๋ถํ๋ฉด ํ ์๋ก ์ธ๋ถ ๋์๊ณผ ์ค์ ์ต์ ๋ค์ด ๊ณ์ ๋์จ๋ค.
AUTO_INCREMENT๋ง ํด๋ ๋จ์ํ ์๋ ์ฆ๊ฐ๊ฐ ์๋๋ผ ์ฆ๊ฐ ๊ฐ๊ฒฉ ์ค์ , ๋ฝ ๋ชจ๋์ ๋ฐ๋ฅธ ๋์ ์ฐจ์ด, ๋ค์ค ํ ์ด๋ธ์์์ ์ถฉ๋ ํํผ ๋ฑ ์์ธ๋ก ๊น์ ์ฃผ์ ๊ฐ ๋ง์๊ณ , TIMESTAMP๋ ํ ํ ์ด๋ธ์ ํ๋๋ง ์๋ ์ ๋ฐ์ดํธ ๊ฐ๋ฅํ๋ค๋ ์ง, ์๊ฐ๋ ์ค์ ๊ณผ์ ๊ด๊ณ ๋ฑ ์ค๋ฌด์ ์ํฅ์ ์ฃผ๋ ์์๊ฐ ์จ์ด ์์๋ค.
์์ง ์ด ๊ธ์์๋ ๋ค๋ฃจ์ง ์์์ง๋ง, ๋์ค์๋ ๋ฝ ๋ชจ๋(Lock Mode)๋ ID ์ฆ๊ฐ๊ฐ ํ๋, ํธ๋ฆฌ๊ฑฐ๋ฅผ ํ์ฉํ ์ ์ฝ ๋ณด์ ๊ฐ์ ๋ด์ฉ๋ ์ ๋ฆฌํด๋ณด๊ณ ์ถ๋ค. ํ ์ด๋ธ ์ค๊ณ๋ ๋จ์ํ ์ปฌ๋ผ ๋์ด์ด ์๋๋ผ, ๋ฐ์ดํฐ ๋ฌด๊ฒฐ์ฑ๊ณผ ์ฑ๋ฅ์ ํจ๊ป ๊ณ ๋ฏผํ๋ ์์ ์ด๋ผ๋ ๊ฑธ ์ ์ ์ฒด๊ฐํ๊ณ ์๋ค.
