
โ ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ ๊ทํ๋? (Normalization)
๋ฐ์ดํฐ ์ค๋ณต์ ์ค์ด๊ณ , ๊ตฌ์กฐ๋ฅผ ๊น๋ํ๊ฒ ๋ง๋ค์ด ๋ฌด๊ฒฐ์ฑ์ ์ ์งํ๋ ์ค๊ณ ๋ฐฉ๋ฒ
โ ์ 1์ ๊ทํ (1NF)
์ปฌ๋ผ์ ์์๊ฐ(Atomic)๋ง ๊ฐ์ ธ์ผ ํ๋ค

โก ์ 2์ ๊ทํ (2NF)
๋ถ๋ถ ํจ์ ์ข ์ ์ ๊ฑฐ

โข ์ 3์ ๊ทํ (3NF)
์ดํ์ ์ข ์ ์ ๊ฑฐ

โ Foreign Key
๋ค๋ฅธ ํ ์ด๋ธ์ Primary Key๋ฅผ ์ฐธ์กฐํ๋ Column
CREATE TABLE dogs (
dog_id BIGINT UNSIGNED PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(50) NOT NULL, weight DECIMAL(5, 2),
date_of_birth DATE,
owner_id BIGINT UNSIGNED,
breed_id BIGINT UNSIGNED
);
owner_id์ breed_id๋ Foreign Key
Foreign Key Constraint
CREATE TABLE dogs (
dog_id BIGINT UNSIGNED PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(50) NOT NULL,
weight DECIMAL(5, 2),
date_of_birth DATE,
owner_id BIGINT UNSIGNED,
breed_id BIGINT UNSIGNED,
FOREIGN KEY (owner_id) REFERENCES owners (owner_id),
CONSTRAINT breed_fk FOREIGN KEY (breed_id) REFERENCES breeds (breed_id)
);
Foreign Key Constraint๋ ์ด๋ฆ์ ์ง์ ํด์ค ์ ์๋ค.(์ถํ์ ์ ์ฝ์ ์ญ์ ํ๊ณ ์ถ์ ๋ ์ด๋ฆ์ผ๋ก ์ญ์ ํ ์ ์๋ค.)
ON DELETE
FOREIGN KEY (owner_id) REFERENCES owners (owner_id) ON DELETE CASCADE,
owner๊ฐ ์ญ์ ๋์ ๋ ํด๋น dog๋ ์ญ์ .
(owner_id๊ฐ update ๋์์ ๋ ์ค์ ์ด ๊ฐ๋ฅํ ON UPDATE๋ ์์ง๋ง id๊ฐ ์ ๋ฐ์ดํธ ๋๋ ๊ฒฝ์ฐ๋ ๋๋ฌผ๋ค.)
FOREIGN KEY (owner_id) REFERENCES owners (owner_id) ON DELETE SET NULL,
owner๊ฐ ์ญ์ ๋์ ๋ ํด๋น dog์์ owner_id ๊ฐ์ null๋ก ์ค์
(NOT NULL ์ ์ฝ์ด ์์ด์ผ ํ๋ค.)
owner_id BIGINT UNSIGNED,
breed_id BIGINT UNSIGNED DEFAULT 2,
FOREIGN KEY (owner_id) REFERENCES owners (owner_id) ON DELETE SET NULL,
CONSTRAINT breed_fk FOREIGN KEY (breed_id) REFERENCES breeds (breed_id) ON DELETE SET DEFAULT
breed๊ฐ ์ญ์ ๋์ ๋ ํด๋น dog์ breed_id ๊ฐ์ ๊ธฐ๋ณธ๊ฐ(2)์ผ๋ก ์ค์
(MySQL์์๋ SET DEFAULT๋ฅผ ์ง์ํ์ง ์๋๋ค.)
CREATE TABLE dogs (
dog_id BIGINT UNSIGNED PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(50) NOT NULL,
weight DECIMAL(5, 2),
date_of_birth DATE,
owner_id BIGINT UNSIGNED,
breed_id BIGINT UNSIGNED DEFAULT 2,
-- FOREIGN KEY (owner_id) REFERENCES owners (owner_id) ON DELETE SET NULL,
CONSTRAINT breed_fk FOREIGN KEY (breed_id) REFERENCES breeds (breed_id) ON DELETE SET DEFAULT
);
ALTER TABLE dogs CONSTRAINT owner_fkFOREIGN KEY (owner_id) REFERENCES owners (owner_id) ON DELETE SET NULL;
์ ์ฝ์ ์๋ก ์ถ๊ฐํด์ผ ํ ๋ dogs table์ ๊ตณ์ด ์ญ์ ํ๊ณ ๋ค์ ์ถ๊ฐํ ํ์์์ด ๋ค์๊ณผ ๊ฐ์ด ์ถ๊ฐ๊ฐ ๊ฐ๋ฅํ๋ค.
ALTER TABLE dogs
DROP FOREIGN KEY owner_fk,
CONSTRAINT owner_fk FOREIGN KEY (owner_id) REFERENCES owners (owner_id) ON DELETE SET NULL;
Foreign Key ์ ์ฝ ์กฐ๊ฑด์ ์์ ํ ๋๋ ๋จผ์ ์ญ์ ํ๋ค๊ฐ ๋ค์ ์ค์ ์ ํ๋ค.
(PostgreSQL์์๋ DROP CONSTRAINT๋ฅผ ์ฌ์ฉํ์ง๋ง, MySQL์์๋ DROP FOREIGN KEY๋ก Foreign Key๋ฅผ ์ญ์ ํด์ผ ํ๋ค.)
โ One to Many, Many to One
1. One-To-Many (1:N) ๊ด๊ณ
ํ ํ
์ด๋ธ์ ํ๋์ ๋ ์ฝ๋๊ฐ, ๋ค๋ฅธ ํ
์ด๋ธ์ ์ฌ๋ฌ ๋ ์ฝ๋์ ์ฐ๊ฒฐ๋๋ ๊ด๊ณ
(1:N์ ์ธ๋ ํค๋ง ์์ผ๋ฉด ํํ ๊ฐ๋ฅ)
ex) ํ ๋ช
์ ์ฃผ์ธ์ ์ฌ๋ฌ ๋ง๋ฆฌ ๊ฐ์์ง๋ฅผ ๊ฐ์ง ์ ์๋ค.
2. One-To-One (1:1) ๊ด๊ณ
๋ ํ
์ด๋ธ ์ฌ์ด์์, ํ๋์ ๋ ์ฝ๋๊ฐ ๋ค๋ฅธ ํ
์ด๋ธ์ ์ค์ง ํ๋์ ๋ ์ฝ๋์๋ง ์ฐ๊ฒฐ๋๋ ๊ด๊ณ
(1:1์ ์ธ๋ ํค + UNIQUE ์กฐ๊ฑด์ด ์์ด์ผ ๊ฐ์ ๊ฐ๋ฅ)
ex) ํ ๋ง๋ฆฌ์ ๊ฐ์์ง๋ ํ๋์ ์ฌ๊ถ๋ง ๊ฐ์ง ์ ์๋ค.
โ Many to Many
SQL์ ๋ค ๋ ๋ค ๊ด๊ณ(N:N relationship)๋ฅผ ์ ์ํ ์ ์์ด์ ์ค๊ฐ ํ ์ด๋ธ(bridge table, link table)์ ๋ง๋ค์ด์ผ ํ๋ค.
CREATE TABLE tricks (trick_id BIGINT UNSIGNED PRIMARY KEY auto_increment, name VARCHAR(50) UNIQUE NOT NULL, difficulty ENUM('easy', 'medium', 'hard') NOT NULL DEFAULT 'easy');
CREATE TABLE dog_tricks (
dog_id BIGINT UNSIGNED,
trick_id BIGINT UNSIGNED,
proficiency ENUM('begginer', 'intermediate', 'expert') NOT NULL DEFAULT 'begginer',
date_learned TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (dog_id, trick_id),
FOREIGN KEY (dog_id) REFERENCES dogs (dog_id) ON DELETE CASCADE,
FOREIGN KEY (trick_id) REFERENCES tricks (trick_id) ON DELETE CASCADE
);
dog_id์ trick_id์ ์กฐํฉ์ Primary Key๋ก ์ฌ์ฉํ์ฌ ๋์ ์กฐํฉ์ด uniqueํด์ผํจ์ ์ ์ํ๋ค.
(๋์ผํ dog์ด ๋์ผํ trick์ ์ค๋ณต์ผ๋ก ๋ฐฐ์ธ ์ ์๋ค.)
โ JOIN
์ฌ๋ฌ ํ ์ด๋ธ์ ์ฐ๊ฒฐํด ํ๋์ ๊ฒฐ๊ณผ๋ก ๋ง๋ค ์ ์๋ค.
CROSS JOIN
๋ณ๋ก ์ ์ฉํ์ง ์๋ค.
์ฒซ ๋ฒ์งธ ํ ์ด๋ธ์ ๋ชจ๋ row์ ๋ ๋ฒ์งธ ํ ์ด๋ธ์ ๋ชจ๋ row๋ฅผ ๊ฐ๊ฐ ์ฐ๊ฒฐ์ํจ๋ค.
SELECT
*
FROM
dogs
CROSS JOIN owners;
use case: ๊ฐ์ ์ฃผ์ธ ์ฌ์ด์ ๋ชจ๋ ์กฐํฉ์ ์์๋ณด๊ณ ์ถ์ ๋
INNER JOIN
๊ฐ์ฅ ๋ง์ด ์ฌ์ฉํ๊ฒ ๋ JOIN
SELECT
*
FROM
dogs
INNER JOIN owners;
INNER ์์ด JOIN๋ง ์ฌ์ฉํด๋ INNER๋ฅผ ์ ์ ๊ฒ๊ณผ ๋์ผํ๊ฒ ์๋ํ๋ค.
SELECT
*
FROM
dogs
JOIN owners;
์กฐ๊ฑด์ ์ ์ด์ row๋ฅผ ๋งค์นญ์ํฌ ์ ์๋ค.
SELECT
*
FROM
dogs
JOIN owners ON dogs.owner_id = owners.owner_id;
dogs ํ ์ด๋ธ์ owner_id์ owners ํ ์ด๋ธ์ owner_id๊ฐ ๊ฐ์ row๋ค๋ง ๋งค์นญ
์กฐ๊ฑด์ ์ ์ง ์์ผ๋ฉด JOIN์ CROSS JOIN์ด ๋๋ค.
USING
SELECT
dogs.name AS dog_name,
owners.name AS owner_name,
breeds.name AS breed_name
FROM
dogs
JOIN owners USING (owner_id)
JOIN breeds ON dogs.breed_id = breeds.breed_id;
ON์ผ๋ก ์กฐ๊ฑด์ ์์ฑํ ๋ ๊ฐ์ column ์ด๋ฆ์ ์ฌ์ฉํ๋ฉด USING์ผ๋ก ์งง๊ฒ ์์ฑํ ์ ์๋ค.
OUTER JOIN
2๊ฐ์ง ์ข ๋ฅ๊ฐ ์๋๋ฐ ์ ์ฉํ๋ค.
1. LEFT OUTER JOIN (LEFT JOIN)
2. RIGHT OUTER JOIN (RIGHT JOIN)
(LEFT ํน์ RIGHT์ ์ ์ผ๋ฉด OUTER๋ ํ์ ํค์๋๊ฐ ์๋๋ค.)
์ ๋งคํ๊ฑฐ๋ ์๋ฏธ๊ฐ ๋ถ๋ถ๋ช ํ row๋ฅผ ํ์ธํด์ผ ํ ๋ ์ฌ์ฉํ๋ค.
SELECT
dogs.name AS dog_name,
owners.name AS owner_name
FROM
dogs
LEFT JOIN owners USING (owner_id);
LEFT์ ํด๋นํ๋ dogs์ ๋ชจ๋ row๋ฅผ ๊ฐ์ ธ์ค๊ณ ๋งค์นญ ๋๋ ๊ฒ์ ๋งค์นญ ์ํค๊ณ owner_id ๊ฐ์ด null์ธ dog๋ ํ์ํด์ค๋ค.
SQLite์์๋ CROSS JOIN, INNER JOIN, LEFT OUTER JOIN๋ง ์ง์ํ๋ค.
โ SELECT๋ฌธ์ ๊ฐ์ผ๋ก column ์ฑ์ฐ๊ธฐ
INSERT INTO
statuses (status_name)
SELECT
status
FROM
movies
GROUP BY
status;
โ ๊ธฐ์กด Table์ Foreign key๋ฅผ ๊ฐ์ง๋ ์ column ์์ฑํ๊ธฐ
ALTER TABLE movies
ADD COLUMN status_id BIGINT UNSIGNED;
ALTER TABLE movies
ADD CONSTRAINT fk_status FOREIGN KEY (status_id) REFERENCES statuses (status_id) ON DELETE SET NULL;
๊ทธ๋ฆฌ๊ณ ๊ทธ column์ movies table์์ status column๊ณผ ๊ฐ์ ์ด๋ฆ์ ๊ฐ์ง๋ status๋ฅผ statuses table์ status_id๋ฅผ ๊ฐ์ ธ์ ๋ฐฉ๊ธ ๋ง๋ ์ column์ ๋ฃ์ด์ฃผ๊ธฐ
UPDATE movies
SET
status_id = (
SELECT
status_id
FROM
statuses
WHERE
status_name = movies.status
);
๋ง์ง๋ง์ผ๋ก ๊ธฐ์กด movies์ status column์ ์ญ์ ํด์ฃผ๋ฉด ๋๋ค.
ALTER TABLE movies
DROP COLUMN status;'๐งฉ SQL' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
| SQL - MySQL, Event & Trigger (0) | 2026.03.31 |
|---|---|
| SQL - MySQL, UNION (0) | 2026.03.27 |
| SQL - MySQL, ๋ฌธ๋ฒ (0) | 2026.03.24 |
| SQL - MySQL Data Types (0) | 2026.03.23 |
| SQL - MySQL Setup (0) | 2026.03.23 |