Ver3.0 ๐ก๏ธ ๋ฐ์ดํฐ ๋ฌด๊ฒฐ์ฑ๊ณผ ์ ์ฝ์กฐ๊ฑด ํ์ฉํ๊ธฐ

๐ก๏ธ ๋ฐ์ดํฐ ๋ฌด๊ฒฐ์ฑ๊ณผ ์ ์ฝ์กฐ๊ฑด ํ์ฉํ๊ธฐ
๋ฐ์ดํฐ๋ฒ ์ด์ค์ ๋ ๋ ํ ๋ฐฉํจ๋ง์ด, ์ ์ฝ์กฐ๊ฑด ์์ ์ ๋ณต!
๐ฏ ๋ฐ์ดํฐ ๋ฌด๊ฒฐ์ฑ, ์ ์ค์ํ ๊น?
์๋
! ์ค๋์ ๋ฐ์ดํฐ๋ฒ ์ด์ค์์ ์ ๋ง์ ๋ง ์ค์ํ ๊ฐ๋
์ธ ๋ฐ์ดํฐ ๋ฌด๊ฒฐ์ฑ๊ณผ ์ ์ฝ์กฐ๊ฑด์ ๋ํด ์ด์ผ๊ธฐํด๋ณผ๊ฒ. ๐
์์ํด๋ด. ๋๊ฐ ์จ๋ผ์ธ ์ผํ๋ชฐ์ ์ด์ํ๋๋ฐ, ์ด๋ ๋ ๊ณ ๊ฐ ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ฅผ ํ์ธํ๋๋ ์ด๋ฉ์ผ ์ฃผ์๊ฐ ์๋ ํ์์ด ์๊ณ , ์ฃผ๋ฌธ ํ
์ด๋ธ์๋ ์กด์ฌํ์ง ์๋ ์ํ ๋ฒํธ๊ฐ ๋ค์ด๊ฐ ์๊ณ , ๊ฐ์ ์ฃผ๋ฌธ๋ฒํธ๊ฐ ์ค๋ณต์ผ๋ก ์ฌ๋ฌ ๊ฐ ์๋ค๋ฉด? ๐คฏ
์ด๊ฑด ๋จ์ํ ๋ฐ์ดํฐ๊ฐ '์ง์ ๋ถํ๋ค'๋ ์์ค์ด ์๋์ผ. ์์คํ
์ ์ฒด๊ฐ ์ค์๋ํ ์ ์๋ ์ฌ๊ฐํ ๋ฌธ์ ์ง! ๋ฐ๋ก ์ด๋ฐ ์ํฉ์ ๋ฐฉ์งํ๊ธฐ ์ํด ์ฐ๋ฆฌ๋ ๋ฐ์ดํฐ ๋ฌด๊ฒฐ์ฑ(Data Integrity)์ด๋ผ๋ ๊ฐ๋
์ ์ฌ์ฉํด.
๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ ์ฅ๋ ๋ฐ์ดํฐ๊ฐ ์ ํํ๊ณ , ์ผ๊ด๋๋ฉฐ, ์ ํจํ ์ํ๋ฅผ ์ ์งํ๋ ๊ฒ์ ๋งํด. ์ฝ๊ฒ ๋งํ๋ฉด "๋ฐ์ดํฐ๊ฐ ๋ง๊ฐ์ง์ง ์๊ณ ๋ฏฟ์ ์ ์๋ ์ํ"๋ผ๊ณ ์๊ฐํ๋ฉด ๋ผ!
๐ ๊ฐ์ฒด ๋ฌด๊ฒฐ์ฑ (Entity Integrity)
์ฒซ ๋ฒ์งธ๋ก ์์๋ณผ ๊ฑด ๊ฐ์ฒด ๋ฌด๊ฒฐ์ฑ์ด์ผ. ์ด๊ฑด ํ
์ด๋ธ์ ๊ฐ ํ(row)์ ๊ณ ์ ํ๊ฒ ์๋ณํ ์ ์์ด์ผ ํ๋ค๋ ์์น์ด์ง.
์๊ฐํด๋ด. ํ์ ๋ช
๋จ์ ํ๋ฒ์ด ์๊ฑฐ๋, ๊ฐ์ ํ๋ฒ์ ๊ฐ์ง ํ์์ด ์ฌ๋ฌ ๋ช
์๋ค๋ฉด? ๋๊ฐ ๋๊ตฐ์ง ๊ตฌ๋ถํ ์๊ฐ ์์์! ๐ฑ
1๏ธโฃ ๋ชจ๋ ํ ์ด๋ธ์ ๊ธฐ๋ณธํค(Primary Key)๋ฅผ ๊ฐ์ ธ์ผ ํด
2๏ธโฃ ๊ธฐ๋ณธํค๋ NULL ๊ฐ์ ๊ฐ์ง ์ ์์ด
3๏ธโฃ ๊ธฐ๋ณธํค๋ ์ค๋ณต๋ ๊ฐ์ ๊ฐ์ง ์ ์์ด
์ค์ SQL๋ก ์ด๋ป๊ฒ ๊ตฌํํ๋์ง ๋ณผ๊น? ๐ค
-- ํ์ ํ
์ด๋ธ ์์ฑ (๊ธฐ๋ณธํค ์ค์ )
CREATE TABLE students (
student_id INT PRIMARY KEY, -- ๊ธฐ๋ณธํค ์ง์
name VARCHAR(50) NOT NULL,
email VARCHAR(100),
enrollment_date DATE
);
-- ๋๋ ํ
์ด๋ธ ๋ ๋ฒจ์์ ๊ธฐ๋ณธํค ์ง์
CREATE TABLE students (
student_id INT,
name VARCHAR(50) NOT NULL,
email VARCHAR(100),
enrollment_date DATE,
CONSTRAINT pk_student PRIMARY KEY (student_id)
);
-- ๋ณตํฉ ๊ธฐ๋ณธํค (์ฌ๋ฌ ์ปฌ๋ผ ์กฐํฉ)
CREATE TABLE course_enrollment (
student_id INT,
course_id INT,
enrollment_date DATE,
PRIMARY KEY (student_id, course_id) -- ๋ ์ปฌ๋ผ ์กฐํฉ์ด ๊ธฐ๋ณธํค
);
์ ์ฝ๋์์ PRIMARY KEY ์ ์ฝ์กฐ๊ฑด์ ์ฌ์ฉํ๋ฉด, ๋ฐ์ดํฐ๋ฒ ์ด์ค๊ฐ ์๋์ผ๋ก:
โ
NULL ๊ฐ ์
๋ ฅ์ ์ฐจ๋จํด
โ
์ค๋ณต๋ ๊ฐ ์
๋ ฅ์ ์ฐจ๋จํด
โ
์๋์ผ๋ก ์ธ๋ฑ์ค๋ฅผ ์์ฑํด์ ๊ฒ์ ์๋๋ฅผ ๋์ฌ์ค
๊ธฐ๋ณธํค๋ก ์ฌ์ฉํ ์ปฌ๋ผ์ ์ ํํ ๋๋ ์ ๋ ๋ณํ์ง ์์ ๊ฐ์ ์ ํํด์ผ ํด! ์๋ฅผ ๋ค์ด ์ด๋ฉ์ผ ์ฃผ์๋ ์ ํ๋ฒํธ๋ ๋ณ๊ฒฝ๋ ์ ์์ผ๋๊น ๊ธฐ๋ณธํค๋ก ์ ํฉํ์ง ์์. ๋์ ์๋ ์ฆ๊ฐํ๋ ID ๊ฐ์ ์ฌ์ฉํ๋ ๊ฒ ์ผ๋ฐ์ ์ด์ผ.
๐ ์ฐธ์กฐ ๋ฌด๊ฒฐ์ฑ (Referential Integrity)
์ด์ ๋ ๋ฒ์งธ, ์ฐธ์กฐ ๋ฌด๊ฒฐ์ฑ์ ๋ํด ์์๋ณด์! ์ด๊ฑด ํ
์ด๋ธ ๊ฐ์ ๊ด๊ณ๋ฅผ ์ ์งํ๋ ๊ท์น์ด์ผ.
์๋ฅผ ๋ค์ด๋ณผ๊ฒ. ์ฃผ๋ฌธ ํ
์ด๋ธ์ "์ํ๋ฒํธ 999๋ฒ์ ์ฃผ๋ฌธํ๋ค"๋ ๋ฐ์ดํฐ๊ฐ ์๋๋ฐ, ์ํ ํ
์ด๋ธ์๋ 999๋ฒ ์ํ์ด ์๋ค๋ฉด? ์ด๊ฑด ๋ง์ด ์ ๋๋ ์ํฉ์ด์ง! ๐ค
์ฐธ์กฐ ๋ฌด๊ฒฐ์ฑ์ ๋ฐ๋ก ์ด๋ฐ "์กด์ฌํ์ง ์๋ ๋ฐ์ดํฐ๋ฅผ ์ฐธ์กฐํ๋ ์ํฉ"์ ๋ฐฉ์งํด์ค.
์ธ๋ํค(Foreign Key)๋ ๋ฐ๋์ ์ฐธ์กฐํ๋ ํ ์ด๋ธ์ ๊ธฐ๋ณธํค ๊ฐ์ด๊ฑฐ๋ NULL์ด์ด์ผ ํด!
์ฝ๊ฒ ๋งํ๋ฉด: "์๋ ๋ฐ์ดํฐ๋ฅผ ๊ฐ๋ฆฌํฌ ์ ์๋ค!"
-- ์ํ ํ
์ด๋ธ (๋ถ๋ชจ ํ
์ด๋ธ)
CREATE TABLE products (
product_id INT PRIMARY KEY,
product_name VARCHAR(100) NOT NULL,
price DECIMAL(10, 2),
stock_quantity INT
);
-- ์ฃผ๋ฌธ ํ
์ด๋ธ (์์ ํ
์ด๋ธ)
CREATE TABLE orders (
order_id INT PRIMARY KEY,
customer_id INT,
product_id INT,
order_date DATE,
quantity INT,
CONSTRAINT fk_product
FOREIGN KEY (product_id)
REFERENCES products(product_id)
);
-- ์ด์ ์ด๋ฐ ์ํฉ์ด ๋ฐ์ํด:
INSERT INTO orders (order_id, customer_id, product_id, quantity)
VALUES (1, 100, 999, 2); -- โ ์๋ฌ! product_id 999๋ products ํ
์ด๋ธ์ ์์!
์ธ๋ํค ์ ์ฝ์กฐ๊ฑด์ ์ค์ ํ๋ฉด ๋ฐ์ดํฐ๋ฒ ์ด์ค๊ฐ ์๋์ผ๋ก ์ฐธ์กฐ ๋ฌด๊ฒฐ์ฑ์ ๊ฒ์ฌํด์ค. ์กด์ฌํ์ง ์๋ ์ํ์ ์ฃผ๋ฌธํ๋ ค๊ณ ํ๋ฉด ์๋ฌ๊ฐ ๋ฐ์ํ์ง! ๐ช
๐ฎ ์ฐธ์กฐ ๋ฌด๊ฒฐ์ฑ ์ต์ ๋ค
์ธ๋ํค๋ฅผ ์ค์ ํ ๋ ๋ถ๋ชจ ํ ์ด๋ธ์ ๋ฐ์ดํฐ๊ฐ ์ญ์ ๋๊ฑฐ๋ ์์ ๋ ๋ ์ด๋ป๊ฒ ํ ์ง ์ ํ ์ ์์ด. ์ด๊ฒ ์ง์ง ์ค์ํ๋ฐ, ์ค๋ฌด์์ ๋ง์ด ์ฌ์ฉํ๊ฑฐ๋ ! ๐
| ์ต์ | ์ค๋ช | ์ฌ์ฉ ์์ |
|---|---|---|
| CASCADE | ๋ถ๋ชจ ๋ฐ์ดํฐ ์ญ์ /์์ ์ ์์ ๋ฐ์ดํฐ๋ ํจ๊ป ์ญ์ /์์ | ์ํ ์ญ์ ์ ๊ด๋ จ ์ฃผ๋ฌธ๋ ๋ชจ๋ ์ญ์ |
| SET NULL | ๋ถ๋ชจ ๋ฐ์ดํฐ ์ญ์ ์ ์์์ ์ธ๋ํค๋ฅผ NULL๋ก ์ค์ | ์นดํ ๊ณ ๋ฆฌ ์ญ์ ์ ์ํ์ ์นดํ ๊ณ ๋ฆฌ๋ฅผ NULL๋ก |
| SET DEFAULT | ๋ถ๋ชจ ๋ฐ์ดํฐ ์ญ์ ์ ์์์ ์ธ๋ํค๋ฅผ ๊ธฐ๋ณธ๊ฐ์ผ๋ก ์ค์ | ๋ถ์ ์ญ์ ์ ์ง์์ '๋ฏธ๋ฐฐ์น' ๋ถ์๋ก |
| RESTRICT | ์์ ๋ฐ์ดํฐ๊ฐ ์์ผ๋ฉด ๋ถ๋ชจ ๋ฐ์ดํฐ ์ญ์ ๋ถ๊ฐ | ์ฃผ๋ฌธ์ด ์๋ ๊ณ ๊ฐ์ ์ญ์ ๋ถ๊ฐ |
| NO ACTION | RESTRICT์ ์ ์ฌํ์ง๋ง ์ฒดํฌ ์์ ์ด ๋ค๋ฆ | ํธ๋์ญ์ ์ข ๋ฃ ์์ ์ ์ฒดํฌ |
-- CASCADE ์์: ์ํ ์ญ์ ์ ๊ด๋ จ ์ฃผ๋ฌธ๋ ์ญ์
CREATE TABLE orders (
order_id INT PRIMARY KEY,
product_id INT,
quantity INT,
CONSTRAINT fk_product_cascade
FOREIGN KEY (product_id)
REFERENCES products(product_id)
ON DELETE CASCADE -- ์ํ ์ญ์ ์ ์ฃผ๋ฌธ๋ ์ญ์
ON UPDATE CASCADE -- ์ํ ID ๋ณ๊ฒฝ ์ ์ฃผ๋ฌธ์ ID๋ ๋ณ๊ฒฝ
);
-- SET NULL ์์: ์นดํ
๊ณ ๋ฆฌ ์ญ์ ์ ์ํ์ ์นดํ
๊ณ ๋ฆฌ๋ฅผ NULL๋ก
CREATE TABLE products (
product_id INT PRIMARY KEY,
product_name VARCHAR(100),
category_id INT,
CONSTRAINT fk_category_null
FOREIGN KEY (category_id)
REFERENCES categories(category_id)
ON DELETE SET NULL -- ์นดํ
๊ณ ๋ฆฌ ์ญ์ ์ NULL๋ก ์ค์
);
-- RESTRICT ์์: ์ฃผ๋ฌธ์ด ์๋ ๊ณ ๊ฐ์ ์ญ์ ๋ถ๊ฐ
CREATE TABLE orders (
order_id INT PRIMARY KEY,
customer_id INT,
CONSTRAINT fk_customer_restrict
FOREIGN KEY (customer_id)
REFERENCES customers(customer_id)
ON DELETE RESTRICT -- ์ฃผ๋ฌธ์ด ์์ผ๋ฉด ๊ณ ๊ฐ ์ญ์ ๋ถ๊ฐ
);
์ค๋ฌด์์๋ CASCADE๋ฅผ ์ฌ์ฉํ ๋ ์ ๋ง ์กฐ์ฌํด์ผ ํด! ์ค์๋ก ์ค์ํ ๋ฐ์ดํฐ๋ฅผ ํ ๋ฒ์ ๋ ๋ ค๋ฒ๋ฆด ์ ์๊ฑฐ๋ . ๐ฑ
๋ณดํต์ RESTRICT๋ NO ACTION์ ๊ธฐ๋ณธ์ผ๋ก ์ฌ์ฉํ๊ณ , ์ ๋ง ํ์ํ ๊ฒฝ์ฐ์๋ง CASCADE๋ฅผ ์ฌ์ฉํ๋ ๊ฒ ์์ ํด.
๐ ๋๋ฉ์ธ ๋ฌด๊ฒฐ์ฑ (Domain Integrity)
์ธ ๋ฒ์งธ๋ ๋๋ฉ์ธ ๋ฌด๊ฒฐ์ฑ์ด์ผ! ์ด๊ฑด ๊ฐ ์ปฌ๋ผ์ ๋ค์ด๊ฐ ์ ์๋ ๊ฐ์ ๋ฒ์๋ ํ์์ ์ ํํ๋ ๊ฑฐ์ง.
์๋ฅผ ๋ค์ด ๋์ด ์ปฌ๋ผ์ -50์ด๋ 300 ๊ฐ์ ๋ง๋ ์ ๋๋ ๊ฐ์ด ๋ค์ด๊ฐ๋ฉด ์ ๋์์? ๋๋ ์ด๋ฉ์ผ ํ์์ด ์๋ ๊ฐ์ด ์ด๋ฉ์ผ ์ปฌ๋ผ์ ๋ค์ด๊ฐ๋ ๊ฒ๋ ๋ง์์ผ ํ๊ณ ! ๐ฏ
๐ ๏ธ ๋๋ฉ์ธ ๋ฌด๊ฒฐ์ฑ์ ์ํ ์ ์ฝ์กฐ๊ฑด๋ค
๋๋ฉ์ธ ๋ฌด๊ฒฐ์ฑ์ ์งํค๊ธฐ ์ํด ์ฌ๋ฌ ๊ฐ์ง ์ ์ฝ์กฐ๊ฑด์ ์ฌ์ฉํ ์ ์์ด. ํ๋์ฉ ์ดํด๋ณด์!
์ปฌ๋ผ์ NULL ๊ฐ์ด ๋ค์ด๊ฐ๋ ๊ฑธ ๋ง์์ค. ํ์ ์ ๋ ฅ ํญ๋ชฉ์ ์ง์ ํ ๋ ์ฌ์ฉํ์ง!
CREATE TABLE users (
user_id INT PRIMARY KEY,
username VARCHAR(50) NOT NULL, -- ํ์ ์
๋ ฅ
email VARCHAR(100) NOT NULL, -- ํ์ ์
๋ ฅ
phone VARCHAR(20), -- ์ ํ ์
๋ ฅ (NULL ๊ฐ๋ฅ)
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);
์ปฌ๋ผ ๊ฐ์ด ํ ์ด๋ธ ๋ด์์ ์ ์ผํด์ผ ํ ๋ ์ฌ์ฉํด. ๊ธฐ๋ณธํค๋ ์๋์ง๋ง ์ค๋ณต๋๋ฉด ์ ๋๋ ๊ฐ์ ์ ์ฉํ์ง!
CREATE TABLE users (
user_id INT PRIMARY KEY,
username VARCHAR(50) NOT NULL UNIQUE, -- ์ค๋ณต ๋ถ๊ฐ
email VARCHAR(100) NOT NULL UNIQUE, -- ์ค๋ณต ๋ถ๊ฐ
phone VARCHAR(20) UNIQUE -- NULL์ ํ์ฉํ๋ ๊ฐ์ด ์์ผ๋ฉด ์ค๋ณต ๋ถ๊ฐ
);
-- ๋๋ ํ
์ด๋ธ ๋ ๋ฒจ์์ ์ง์
CREATE TABLE users (
user_id INT PRIMARY KEY,
username VARCHAR(50) NOT NULL,
email VARCHAR(100) NOT NULL,
CONSTRAINT uq_username UNIQUE (username),
CONSTRAINT uq_email UNIQUE (email)
);
์ด๊ฒ ์ง์ง ๊ฐ๋ ฅํด! ํน์ ์กฐ๊ฑด์ ๋ง์กฑํ๋ ๊ฐ๋ง ์ ๋ ฅ๋๋๋ก ํ ์ ์์ด. ๐ช
CREATE TABLE employees (
employee_id INT PRIMARY KEY,
name VARCHAR(100) NOT NULL,
age INT CHECK (age >= 18 AND age <= 70), -- ๋์ด๋ 18~70์ธ
salary DECIMAL(10, 2) CHECK (salary > 0), -- ๊ธ์ฌ๋ ์์
email VARCHAR(100) CHECK (email LIKE '%@%.%'), -- ์ด๋ฉ์ผ ํ์ ์ฒดํฌ
gender CHAR(1) CHECK (gender IN ('M', 'F', 'O')), -- M, F, O ์ค ํ๋
hire_date DATE CHECK (hire_date <= CURRENT_DATE) -- ์
์ฌ์ผ์ ์ค๋ ์ด์
);
-- ๋ณต์กํ CHECK ์ ์ฝ์กฐ๊ฑด
CREATE TABLE products (
product_id INT PRIMARY KEY,
product_name VARCHAR(100) NOT NULL,
price DECIMAL(10, 2),
discount_price DECIMAL(10, 2),
stock_quantity INT,
CONSTRAINT chk_price CHECK (price > 0),
CONSTRAINT chk_discount CHECK (discount_price IS NULL OR discount_price < price),
CONSTRAINT chk_stock CHECK (stock_quantity >= 0)
);
๊ฐ์ ์ ๋ ฅํ์ง ์์์ ๋ ์๋์ผ๋ก ๋ค์ด๊ฐ ๊ธฐ๋ณธ๊ฐ์ ์ค์ ํด์ค.
CREATE TABLE orders (
order_id INT PRIMARY KEY,
customer_id INT NOT NULL,
order_date DATE DEFAULT CURRENT_DATE, -- ๊ธฐ๋ณธ๊ฐ: ์ค๋ ๋ ์ง
status VARCHAR(20) DEFAULT 'PENDING', -- ๊ธฐ๋ณธ๊ฐ: 'PENDING'
is_paid BOOLEAN DEFAULT FALSE, -- ๊ธฐ๋ณธ๊ฐ: FALSE
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- ์ฌ์ฉ ์์
INSERT INTO orders (order_id, customer_id)
VALUES (1, 100);
-- order_date, status, is_paid, created_at๋ ์๋์ผ๋ก ๊ธฐ๋ณธ๊ฐ ์ค์ ๋จ!
๐จ ์ฌ์ฉ์ ์ ์ ๋ฌด๊ฒฐ์ฑ (User-Defined Integrity)
๋ง์ง๋ง์ผ๋ก ์ฌ์ฉ์ ์ ์ ๋ฌด๊ฒฐ์ฑ์ด์ผ! ์ด๊ฑด ๋น์ฆ๋์ค ๊ท์น์ ๋ฐ๋ผ ์ฐ๋ฆฌ๊ฐ ์ง์ ์ ์ํ๋ ์ ์ฝ์กฐ๊ฑด์ด์ง.
์๋ฅผ ๋ค์ด "ํ ์ธ๊ฐ๋ ์ ๊ฐ์ 50%๋ณด๋ค ๋ฎ์ ์ ์๋ค"๊ฑฐ๋ "์ฃผ๋ฌธ ์๋์ ์ฌ๊ณ ์๋์ ์ด๊ณผํ ์ ์๋ค" ๊ฐ์ ๋ณต์กํ ๋น์ฆ๋์ค ๊ท์น์ ๊ตฌํํ ์ ์์ด! ๐ฏ
๐ง ํธ๋ฆฌ๊ฑฐ(Trigger)๋ฅผ ํ์ฉํ ๋ฌด๊ฒฐ์ฑ
ํธ๋ฆฌ๊ฑฐ๋ ํน์ ์ด๋ฒคํธ(INSERT, UPDATE, DELETE)๊ฐ ๋ฐ์ํ์ ๋ ์๋์ผ๋ก ์คํ๋๋ ์ฝ๋์ผ. ๋ณต์กํ ๋น์ฆ๋์ค ๋ก์ง์ ๊ตฌํํ ๋ ์ ๋ง ์ ์ฉํ์ง! ๐
-- ์ฌ๊ณ ์๋ ์ฒดํฌ ํธ๋ฆฌ๊ฑฐ
CREATE TRIGGER check_stock_before_order
BEFORE INSERT ON orders
FOR EACH ROW
BEGIN
DECLARE available_stock INT;
-- ํ์ฌ ์ฌ๊ณ ํ์ธ
SELECT stock_quantity INTO available_stock
FROM products
WHERE product_id = NEW.product_id;
-- ์ฌ๊ณ ๊ฐ ๋ถ์กฑํ๋ฉด ์๋ฌ ๋ฐ์
IF NEW.quantity > available_stock THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = '์ฌ๊ณ ๊ฐ ๋ถ์กฑํฉ๋๋ค!';
END IF;
END;
-- ์ฃผ๋ฌธ ํ ์ฌ๊ณ ์๋ ๊ฐ์ ํธ๋ฆฌ๊ฑฐ
CREATE TRIGGER update_stock_after_order
AFTER INSERT ON orders
FOR EACH ROW
BEGIN
UPDATE products
SET stock_quantity = stock_quantity - NEW.quantity
WHERE product_id = NEW.product_id;
END;
-- ํ ์ธ๊ฐ ๊ฒ์ฆ ํธ๋ฆฌ๊ฑฐ
CREATE TRIGGER validate_discount_price
BEFORE INSERT OR UPDATE ON products
FOR EACH ROW
BEGIN
IF NEW.discount_price IS NOT NULL THEN
-- ํ ์ธ๊ฐ๋ ์ ๊ฐ์ 50% ์ด์์ด์ด์ผ ํจ
IF NEW.discount_price < (NEW.price * 0.5) THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = 'ํ ์ธ๊ฐ๋ ์ ๊ฐ์ 50% ์ด์์ด์ด์ผ ํฉ๋๋ค!';
END IF;
END IF;
END;
๐ ์ ์ฅ ํ๋ก์์ (Stored Procedure)๋ฅผ ํ์ฉํ ๋ฌด๊ฒฐ์ฑ
์ ์ฅ ํ๋ก์์ ๋ฅผ ์ฌ์ฉํ๋ฉด ๋ณต์กํ ๋น์ฆ๋์ค ๋ก์ง์ ์บก์ํํ ์ ์์ด. ๋ฐ์ดํฐ ์ ๋ ฅ ์ ์ ์ฌ๋ฌ ๊ฐ์ง ๊ฒ์ฆ์ ์ํํ ์ ์์ง! ๐ช
-- ์์ ํ ์ฃผ๋ฌธ ์์ฑ ํ๋ก์์
DELIMITER //
CREATE PROCEDURE create_order_safely(
IN p_customer_id INT,
IN p_product_id INT,
IN p_quantity INT
)
BEGIN
DECLARE v_stock INT;
DECLARE v_price DECIMAL(10,2);
DECLARE v_customer_exists INT;
-- ํธ๋์ญ์
์์
START TRANSACTION;
-- 1. ๊ณ ๊ฐ ์กด์ฌ ์ฌ๋ถ ํ์ธ
SELECT COUNT(*) INTO v_customer_exists
FROM customers
WHERE customer_id = p_customer_id;
IF v_customer_exists = 0 THEN
ROLLBACK;
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = '์กด์ฌํ์ง ์๋ ๊ณ ๊ฐ์
๋๋ค!';
END IF;
-- 2. ์ฌ๊ณ ํ์ธ
SELECT stock_quantity, price INTO v_stock, v_price
FROM products
WHERE product_id = p_product_id
FOR UPDATE; -- ๋์์ฑ ์ ์ด๋ฅผ ์ํ ๋ฝ
IF v_stock < p_quantity THEN
ROLLBACK;
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = '์ฌ๊ณ ๊ฐ ๋ถ์กฑํฉ๋๋ค!';
END IF;
-- 3. ์ฃผ๋ฌธ ์์ฑ
INSERT INTO orders (customer_id, product_id, quantity, total_price, order_date)
VALUES (p_customer_id, p_product_id, p_quantity, v_price * p_quantity, CURRENT_DATE);
-- 4. ์ฌ๊ณ ๊ฐ์
UPDATE products
SET stock_quantity = stock_quantity - p_quantity
WHERE product_id = p_product_id;
-- ํธ๋์ญ์
์ปค๋ฐ
COMMIT;
END //
DELIMITER ;
-- ์ฌ์ฉ ์์
CALL create_order_safely(100, 5, 2);
๋ฐ์ดํฐ๋ฒ ์ด์ค ์ค๊ณ๋ ์ ์ฝ์กฐ๊ฑด ๊ตฌํ์ด ์ด๋ ต๋ค๋ฉด, ์ฌ๋ฅ๋ท(https://www.jaenung.net)์์ ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ ๋ฌธ๊ฐ์ ๋์์ ๋ฐ์ ์ ์์ด! ์ค๋ฌด ๊ฒฝํ์ด ํ๋ถํ ๊ฐ๋ฐ์๋ค์ด ํ๋ก์ ํธ์ ๋ง๋ ์ต์ ์ ์ ์ฝ์กฐ๊ฑด ์ค๊ณ๋ฅผ ๋์์ค ๊ฑฐ์ผ. ๐
โก ์ ์ฝ์กฐ๊ฑด ๊ด๋ฆฌํ๊ธฐ
์ ์ฝ์กฐ๊ฑด์ ๋ง๋ค์์ผ๋ฉด ๊ด๋ฆฌ๋ ํ ์ค ์์์ผ๊ฒ ์ง? ์ ์ฝ์กฐ๊ฑด์ ์ถ๊ฐํ๊ณ , ์์ ํ๊ณ , ์ญ์ ํ๋ ๋ฐฉ๋ฒ์ ์์๋ณด์! ๐ ๏ธ
โ ๊ธฐ์กด ํ ์ด๋ธ์ ์ ์ฝ์กฐ๊ฑด ์ถ๊ฐํ๊ธฐ
-- PRIMARY KEY ์ถ๊ฐ
ALTER TABLE users
ADD PRIMARY KEY (user_id);
-- FOREIGN KEY ์ถ๊ฐ
ALTER TABLE orders
ADD CONSTRAINT fk_customer
FOREIGN KEY (customer_id)
REFERENCES customers(customer_id)
ON DELETE RESTRICT
ON UPDATE CASCADE;
-- UNIQUE ์ ์ฝ์กฐ๊ฑด ์ถ๊ฐ
ALTER TABLE users
ADD CONSTRAINT uq_email UNIQUE (email);
-- CHECK ์ ์ฝ์กฐ๊ฑด ์ถ๊ฐ
ALTER TABLE employees
ADD CONSTRAINT chk_age CHECK (age >= 18 AND age <= 70);
-- NOT NULL ์ ์ฝ์กฐ๊ฑด ์ถ๊ฐ (์ปฌ๋ผ ์์ )
ALTER TABLE users
MODIFY email VARCHAR(100) NOT NULL;
-- DEFAULT ๊ฐ ์ถ๊ฐ
ALTER TABLE orders
ALTER COLUMN status SET DEFAULT 'PENDING';
๐๏ธ ์ ์ฝ์กฐ๊ฑด ์ญ์ ํ๊ธฐ
-- PRIMARY KEY ์ญ์
ALTER TABLE users
DROP PRIMARY KEY;
-- FOREIGN KEY ์ญ์
ALTER TABLE orders
DROP FOREIGN KEY fk_customer;
-- UNIQUE ์ ์ฝ์กฐ๊ฑด ์ญ์
ALTER TABLE users
DROP INDEX uq_email;
-- CHECK ์ ์ฝ์กฐ๊ฑด ์ญ์
ALTER TABLE employees
DROP CHECK chk_age;
-- NOT NULL ์ ์ฝ์กฐ๊ฑด ์ ๊ฑฐ (์ปฌ๋ผ ์์ )
ALTER TABLE users
MODIFY email VARCHAR(100) NULL;
-- DEFAULT ๊ฐ ์ ๊ฑฐ
ALTER TABLE orders
ALTER COLUMN status DROP DEFAULT;
๐ ์ ์ฝ์กฐ๊ฑด ์กฐํํ๊ธฐ
ํ์ฌ ํ ์ด๋ธ์ ์ด๋ค ์ ์ฝ์กฐ๊ฑด์ด ์ค์ ๋์ด ์๋์ง ํ์ธํ๋ ๋ฐฉ๋ฒ๋ ์์๋๋ฉด ์ข์! ๐
-- MySQL์์ ์ ์ฝ์กฐ๊ฑด ์กฐํ
SELECT
CONSTRAINT_NAME,
CONSTRAINT_TYPE,
TABLE_NAME,
COLUMN_NAME
FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS tc
JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE kcu
ON tc.CONSTRAINT_NAME = kcu.CONSTRAINT_NAME
WHERE tc.TABLE_SCHEMA = 'your_database_name'
AND tc.TABLE_NAME = 'your_table_name';
-- ์ธ๋ํค ์์ธ ์ ๋ณด ์กฐํ
SELECT
CONSTRAINT_NAME,
TABLE_NAME,
COLUMN_NAME,
REFERENCED_TABLE_NAME,
REFERENCED_COLUMN_NAME
FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE
WHERE TABLE_SCHEMA = 'your_database_name'
AND REFERENCED_TABLE_NAME IS NOT NULL;
-- PostgreSQL์์ ์ ์ฝ์กฐ๊ฑด ์กฐํ
SELECT
con.conname AS constraint_name,
con.contype AS constraint_type,
tbl.relname AS table_name,
col.attname AS column_name
FROM pg_constraint con
JOIN pg_class tbl ON con.conrelid = tbl.oid
JOIN pg_attribute col ON col.attrelid = tbl.oid
WHERE tbl.relname = 'your_table_name';
๐ฏ ์ค์ ์์ : ์จ๋ผ์ธ ์ผํ๋ชฐ ๋ฐ์ดํฐ๋ฒ ์ด์ค
์ด์ ๋ฐฐ์ด ๋ด์ฉ์ ์ข ํฉํด์ ์ค์ ์จ๋ผ์ธ ์ผํ๋ชฐ ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ฅผ ์ค๊ณํด๋ณด์! ๋ชจ๋ ์ข ๋ฅ์ ๋ฌด๊ฒฐ์ฑ๊ณผ ์ ์ฝ์กฐ๊ฑด์ ์ ์ฉํด๋ณผ ๊ฑฐ์ผ. ๐
-- 1. ๊ณ ๊ฐ ํ
์ด๋ธ
CREATE TABLE customers (
customer_id INT AUTO_INCREMENT PRIMARY KEY, -- ๊ฐ์ฒด ๋ฌด๊ฒฐ์ฑ
username VARCHAR(50) NOT NULL UNIQUE, -- ๋๋ฉ์ธ ๋ฌด๊ฒฐ์ฑ
email VARCHAR(100) NOT NULL UNIQUE,
password_hash VARCHAR(255) NOT NULL,
phone VARCHAR(20),
birth_date DATE,
gender CHAR(1) CHECK (gender IN ('M', 'F', 'O')),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
is_active BOOLEAN DEFAULT TRUE,
CONSTRAINT chk_email_format CHECK (email LIKE '%@%.%'),
CONSTRAINT chk_birth_date CHECK (birth_date <= CURRENT_DATE)
);
-- 2. ์นดํ
๊ณ ๋ฆฌ ํ
์ด๋ธ
CREATE TABLE categories (
category_id INT AUTO_INCREMENT PRIMARY KEY,
category_name VARCHAR(50) NOT NULL UNIQUE,
parent_category_id INT,
description TEXT,
CONSTRAINT fk_parent_category
FOREIGN KEY (parent_category_id)
REFERENCES categories(category_id)
ON DELETE SET NULL -- ๋ถ๋ชจ ์นดํ
๊ณ ๋ฆฌ ์ญ์ ์ NULL๋ก
);
-- 3. ์ํ ํ
์ด๋ธ
CREATE TABLE products (
product_id INT AUTO_INCREMENT PRIMARY KEY,
product_name VARCHAR(100) NOT NULL,
category_id INT,
description TEXT,
price DECIMAL(10, 2) NOT NULL,
discount_price DECIMAL(10, 2),
stock_quantity INT NOT NULL DEFAULT 0,
min_order_quantity INT DEFAULT 1,
max_order_quantity INT DEFAULT 999,
is_available BOOLEAN DEFAULT TRUE,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
-- ์ ์ฝ์กฐ๊ฑด๋ค
CONSTRAINT fk_category
FOREIGN KEY (category_id)
REFERENCES categories(category_id)
ON DELETE SET NULL,
CONSTRAINT chk_price CHECK (price > 0),
CONSTRAINT chk_discount CHECK (
discount_price IS NULL OR
(discount_price > 0 AND discount_price < price)
),
CONSTRAINT chk_stock CHECK (stock_quantity >= 0),
CONSTRAINT chk_order_quantity CHECK (
min_order_quantity > 0 AND
max_order_quantity >= min_order_quantity
)
);
-- 4. ์ฃผ๋ฌธ ํ
์ด๋ธ
CREATE TABLE orders (
order_id INT AUTO_INCREMENT PRIMARY KEY,
customer_id INT NOT NULL,
order_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
status VARCHAR(20) DEFAULT 'PENDING',
total_amount DECIMAL(10, 2) NOT NULL,
shipping_address VARCHAR(255) NOT NULL,
payment_method VARCHAR(20),
CONSTRAINT fk_customer
FOREIGN KEY (customer_id)
REFERENCES customers(customer_id)
ON DELETE RESTRICT, -- ์ฃผ๋ฌธ์ด ์๋ ๊ณ ๊ฐ์ ์ญ์ ๋ถ๊ฐ
CONSTRAINT chk_status CHECK (
status IN ('PENDING', 'CONFIRMED', 'SHIPPED', 'DELIVERED', 'CANCELLED')
),
CONSTRAINT chk_total_amount CHECK (total_amount >= 0),
CONSTRAINT chk_payment_method CHECK (
payment_method IN ('CARD', 'BANK_TRANSFER', 'CASH', 'PAYPAL')
)
);
-- 5. ์ฃผ๋ฌธ ์์ธ ํ
์ด๋ธ
CREATE TABLE order_items (
order_item_id INT AUTO_INCREMENT PRIMARY KEY,
order_id INT NOT NULL,
product_id INT NOT NULL,
quantity INT NOT NULL,
unit_price DECIMAL(10, 2) NOT NULL,
subtotal DECIMAL(10, 2) NOT NULL,
CONSTRAINT fk_order
FOREIGN KEY (order_id)
REFERENCES orders(order_id)
ON DELETE CASCADE, -- ์ฃผ๋ฌธ ์ญ์ ์ ์ฃผ๋ฌธ ์์ธ๋ ์ญ์
CONSTRAINT fk_product
FOREIGN KEY (product_id)
REFERENCES products(product_id)
ON DELETE RESTRICT, -- ์ฃผ๋ฌธ๋ ์ํ์ ์ญ์ ๋ถ๊ฐ
CONSTRAINT chk_quantity CHECK (quantity > 0),
CONSTRAINT chk_unit_price CHECK (unit_price > 0),
CONSTRAINT chk_subtotal CHECK (subtotal = quantity * unit_price),
CONSTRAINT uq_order_product UNIQUE (order_id, product_id) -- ๊ฐ์ ์ฃผ๋ฌธ์ ๊ฐ์ ์ํ ์ค๋ณต ๋ฐฉ์ง
);
-- 6. ๋ฆฌ๋ทฐ ํ
์ด๋ธ
CREATE TABLE reviews (
review_id INT AUTO_INCREMENT PRIMARY KEY,
product_id INT NOT NULL,
customer_id INT NOT NULL,
rating INT NOT NULL,
comment TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT fk_review_product
FOREIGN KEY (product_id)
REFERENCES products(product_id)
ON DELETE CASCADE,
CONSTRAINT fk_review_customer
FOREIGN KEY (customer_id)
REFERENCES customers(customer_id)
ON DELETE CASCADE,
CONSTRAINT chk_rating CHECK (rating BETWEEN 1 AND 5),
CONSTRAINT uq_customer_product UNIQUE (customer_id, product_id) -- ๊ณ ๊ฐ๋น ์ํ 1๊ฐ ๋ฆฌ๋ทฐ๋ง
);
1๏ธโฃ ์ฑ๋ฅ ๊ณ ๋ ค: ์ ์ฝ์กฐ๊ฑด์ด ๋ง์์๋ก INSERT/UPDATE ์๋๊ฐ ๋๋ ค์ง ์ ์์ด. ํ์ํ ์ ์ฝ์กฐ๊ฑด๋ง ์ค์ ํ์!
2๏ธโฃ ์ธ๋ฑ์ค ๊ด๋ฆฌ: UNIQUE์ FOREIGN KEY๋ ์๋์ผ๋ก ์ธ๋ฑ์ค๋ฅผ ์์ฑํด. ๋ถํ์ํ ์ ์ฝ์กฐ๊ฑด์ ์ธ๋ฑ์ค ๋ญ๋น์ผ!
3๏ธโฃ CASCADE ์ ์คํ: ON DELETE CASCADE๋ ํธ๋ฆฌํ์ง๋ง ์ค์๋ก ๋๋ ์ญ์ ๋ ์ ์์ด. ์ ๋ง ํ์ํ ๊ฒฝ์ฐ๋ง ์ฌ์ฉ!
4๏ธโฃ ๋ช ๋ช ๊ท์น: ์ ์ฝ์กฐ๊ฑด ์ด๋ฆ์ ๋ช ํํ๊ฒ ์ง์ด์ผ ๋์ค์ ๊ด๋ฆฌํ๊ธฐ ์ฌ์. (์: fk_ํ ์ด๋ธ๋ช _์ปฌ๋ผ๋ช , chk_ํ ์ด๋ธ๋ช _์กฐ๊ฑด๋ช )
๐ ๊ณ ๊ธ ๊ธฐ๋ฒ: ๋ณตํฉ ์ ์ฝ์กฐ๊ฑด๊ณผ ์กฐ๊ฑด๋ถ ์ ์ฝ
์ด์ ์ข ๋ ๊ณ ๊ธ ๊ธฐ๋ฒ์ ์์๋ณผ๊น? ์ค๋ฌด์์ ์ ๋ง ์ ์ฉํ ํ ํฌ๋๋ค์ด์ผ! ๐ก
๐ ๋ณตํฉ ์ ์ฝ์กฐ๊ฑด (Composite Constraints)
์ฌ๋ฌ ์ปฌ๋ผ์ ์กฐํฉํด์ ์ ์ฝ์กฐ๊ฑด์ ๋ง๋ค ์ ์์ด. ์ด๊ฒ ์๊ฐ๋ณด๋ค ์์ฒญ ์ ์ฉํด! ๐
-- ๋ณตํฉ UNIQUE: ๊ฐ์ ๋ ์ง์ ๊ฐ์ ๊ณ ๊ฐ์ด ๊ฐ์ ์ํ์ ์ฌ๋ฌ ๋ฒ ์ฃผ๋ฌธํ ์ ์์
CREATE TABLE daily_orders (
order_id INT AUTO_INCREMENT PRIMARY KEY,
customer_id INT NOT NULL,
product_id INT NOT NULL,
order_date DATE NOT NULL,
quantity INT NOT NULL,
CONSTRAINT uq_daily_order UNIQUE (customer_id, product_id, order_date)
);
-- ๋ณตํฉ CHECK: ์์์ผ๊ณผ ์ข
๋ฃ์ผ ๊ฒ์ฆ
CREATE TABLE promotions (
promotion_id INT AUTO_INCREMENT PRIMARY KEY,
promotion_name VARCHAR(100) NOT NULL,
start_date DATE NOT NULL,
end_date DATE NOT NULL,
discount_rate DECIMAL(5, 2),
CONSTRAINT chk_date_range CHECK (end_date >= start_date),
CONSTRAINT chk_discount_rate CHECK (
discount_rate > 0 AND discount_rate <= 100
)
);
-- ๋ณตํฉ ์ธ๋ํค: ์ฌ๋ฌ ์ปฌ๋ผ์ ์กฐํฉํ ์ฐธ์กฐ
CREATE TABLE course_schedule (
schedule_id INT AUTO_INCREMENT PRIMARY KEY,
course_code VARCHAR(10),
semester VARCHAR(10),
classroom VARCHAR(20),
CONSTRAINT fk_course FOREIGN KEY (course_code, semester)
REFERENCES courses(course_code, semester)
);
๐ญ ์กฐ๊ฑด๋ถ ์ ์ฝ์กฐ๊ฑด
ํน์ ์กฐ๊ฑด์์๋ง ์ ์ฉ๋๋ ์ ์ฝ์กฐ๊ฑด๋ ๋ง๋ค ์ ์์ด! ์ด๊ฑด ์ง์ง ๊ฐ๋ ฅํ ๊ธฐ๋ฅ์ด์ผ. ๐ฅ
-- ์กฐ๊ฑด๋ถ CHECK: ํ ์ธ ์ํ์ผ ๋๋ง ํ ์ธ๊ฐ ํ์
CREATE TABLE products_advanced (
product_id INT AUTO_INCREMENT PRIMARY KEY,
product_name VARCHAR(100) NOT NULL,
price DECIMAL(10, 2) NOT NULL,
is_on_sale BOOLEAN DEFAULT FALSE,
discount_price DECIMAL(10, 2),
CONSTRAINT chk_discount_required CHECK (
(is_on_sale = FALSE) OR
(is_on_sale = TRUE AND discount_price IS NOT NULL AND discount_price < price)
)
);
-- ์กฐ๊ฑด๋ถ UNIQUE: ํ์ฑ ์ํ์ธ ๊ฒ๋ง ์ค๋ณต ๋ถ๊ฐ
-- (MySQL 8.0.13 ์ด์์์ ์ง์ํ๋ ํจ์ ์ธ๋ฑ์ค ํ์ฉ)
CREATE TABLE user_sessions (
session_id INT AUTO_INCREMENT PRIMARY KEY,
user_id INT NOT NULL,
device_type VARCHAR(20),
is_active BOOLEAN DEFAULT TRUE,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- ํ์ฑ ์ธ์
๋ง ์ค๋ณต ๋ฐฉ์งํ๋ ์ธ๋ฑ์ค
CREATE UNIQUE INDEX idx_active_session
ON user_sessions(user_id, device_type, (CASE WHEN is_active THEN 1 END));
-- ์กฐ๊ฑด๋ถ ์ธ๋ํค: NULL์ด ์๋ ๋๋ง ์ฐธ์กฐ ๊ฒ์ฆ
CREATE TABLE optional_manager (
employee_id INT PRIMARY KEY,
employee_name VARCHAR(100) NOT NULL,
manager_id INT, -- NULL ํ์ฉ
CONSTRAINT fk_manager
FOREIGN KEY (manager_id)
REFERENCES optional_manager(employee_id)
ON DELETE SET NULL
-- manager_id๊ฐ NULL์ด๋ฉด ์ธ๋ํค ๊ฒ์ฆ ์ ํจ!
);
โฐ ์๊ฐ ๊ธฐ๋ฐ ์ ์ฝ์กฐ๊ฑด
-- ์์
์๊ฐ ์ฒดํฌ
CREATE TABLE reservations (
reservation_id INT AUTO_INCREMENT PRIMARY KEY,
customer_id INT NOT NULL,
reservation_time DATETIME NOT NULL,
CONSTRAINT chk_business_hours CHECK (
HOUR(reservation_time) >= 9 AND
HOUR(reservation_time) < 22
),
CONSTRAINT chk_future_reservation CHECK (
reservation_time > NOW()
)
);
-- ์ ํจ ๊ธฐ๊ฐ ์ฒดํฌ
CREATE TABLE coupons (
coupon_id INT AUTO_INCREMENT PRIMARY KEY,
coupon_code VARCHAR(20) NOT NULL UNIQUE,
discount_amount DECIMAL(10, 2) NOT NULL,
valid_from DATE NOT NULL,
valid_until DATE NOT NULL,
is_used BOOLEAN DEFAULT FALSE,
CONSTRAINT chk_valid_period CHECK (valid_until >= valid_from),
CONSTRAINT chk_not_expired CHECK (
is_used = TRUE OR valid_until >= CURRENT_DATE
)
);
๐ ์ ์ฝ์กฐ๊ฑด ์๋ฐ ์ฒ๋ฆฌํ๊ธฐ
์ ์ฝ์กฐ๊ฑด์ ์ค์ ํ๋ค๋ฉด, ์๋ฐํ์ ๋ ์ด๋ป๊ฒ ์ฒ๋ฆฌํ ์ง๋ ์์์ผ๊ฒ ์ง? ์๋ฌ ๋ฉ์์ง๋ฅผ ์ ํ์ฉํ๋ฉด ์ฌ์ฉ์ ๊ฒฝํ์ด ํจ์ฌ ์ข์์ ธ! ๐
๐ฏ ์๋ฌ ์ฒ๋ฆฌ ์ ๋ต
-- 1. ํธ๋์ญ์
๊ณผ ํจ๊ป ์ฌ์ฉํ๊ธฐ
START TRANSACTION;
BEGIN
-- ์ฌ๋ฌ ์์
์ํ
INSERT INTO customers (username, email)
VALUES ('john_doe', 'john@example.com');
INSERT INTO orders (customer_id, total_amount)
VALUES (LAST_INSERT_ID(), 50000);
-- ๋ชจ๋ ์์
์ด ์ฑ๊ณตํ๋ฉด ์ปค๋ฐ
COMMIT;
EXCEPTION
WHEN OTHERS THEN
-- ์๋ฌ ๋ฐ์ ์ ๋กค๋ฐฑ
ROLLBACK;
-- ์๋ฌ ๋ก๊น
INSERT INTO error_log (error_message, error_time)
VALUES (SQLERRM, NOW());
END;
-- 2. ์ ์ฅ ํ๋ก์์ ์์ ์๋ฌ ์ฒ๋ฆฌ
DELIMITER //
CREATE PROCEDURE safe_insert_product(
IN p_name VARCHAR(100),
IN p_price DECIMAL(10,2),
IN p_stock INT,
OUT p_result VARCHAR(100)
)
BEGIN
DECLARE EXIT HANDLER FOR SQLEXCEPTION
BEGIN
-- ์๋ฌ ๋ฐ์ ์ ์ฒ๋ฆฌ
GET DIAGNOSTICS CONDITION 1
@sqlstate = RETURNED_SQLSTATE,
@errno = MYSQL_ERRNO,
@text = MESSAGE_TEXT;
SET p_result = CONCAT('์๋ฌ ๋ฐ์: ', @text);
ROLLBACK;
END;
START TRANSACTION;
-- ์ ํจ์ฑ ๊ฒ์ฌ
IF p_price <= 0 THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = '๊ฐ๊ฒฉ์ 0๋ณด๋ค ์ปค์ผ ํฉ๋๋ค!';
END IF;
IF p_stock < 0 THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = '์ฌ๊ณ ๋ ์์์ผ ์ ์์ต๋๋ค!';
END IF;
-- ๋ฐ์ดํฐ ์ฝ์
INSERT INTO products (product_name, price, stock_quantity)
VALUES (p_name, p_price, p_stock);
COMMIT;
SET p_result = '์ํ์ด ์ฑ๊ณต์ ์ผ๋ก ๋ฑ๋ก๋์์ต๋๋ค!';
END //
DELIMITER ;
-- ์ฌ์ฉ ์์
CALL safe_insert_product('๋
ธํธ๋ถ', 1500000, 10, @result);
SELECT @result;
๐ฑ ์ ํ๋ฆฌ์ผ์ด์ ๋ ๋ฒจ์์์ ์ฒ๋ฆฌ
๋ฐ์ดํฐ๋ฒ ์ด์ค ์ ์ฝ์กฐ๊ฑด๊ณผ ํจ๊ป ์ ํ๋ฆฌ์ผ์ด์ ๋ ๋ฒจ์์๋ ๊ฒ์ฆ์ ํ๋ฉด ๋ ์ข์ ์ฌ์ฉ์ ๊ฒฝํ์ ์ ๊ณตํ ์ ์์ด! ๐จ
-- Python ์์ (Flask + SQLAlchemy)
from flask import Flask, request, jsonify
from sqlalchemy.exc import IntegrityError
import re
@app.route('/api/users', methods=['POST'])
def create_user():
try:
data = request.get_json()
# 1. ์ ํ๋ฆฌ์ผ์ด์
๋ ๋ฒจ ๊ฒ์ฆ
if not data.get('email'):
return jsonify({'error': '์ด๋ฉ์ผ์ ํ์์
๋๋ค!'}), 400
# ์ด๋ฉ์ผ ํ์ ๊ฒ์ฆ
email_pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'
if not re.match(email_pattern, data['email']):
return jsonify({'error': '์ฌ๋ฐ๋ฅธ ์ด๋ฉ์ผ ํ์์ด ์๋๋๋ค!'}), 400
# 2. ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ฝ์
new_user = User(
username=data['username'],
email=data['email']
)
db.session.add(new_user)
db.session.commit()
return jsonify({'message': '์ฌ์ฉ์๊ฐ ์์ฑ๋์์ต๋๋ค!'}), 201
except IntegrityError as e:
db.session.rollback()
# ์ ์ฝ์กฐ๊ฑด ์๋ฐ ํ์
๋ณ ์ฒ๋ฆฌ
error_message = str(e.orig)
if 'Duplicate entry' in error_message:
if 'email' in error_message:
return jsonify({'error': '์ด๋ฏธ ์ฌ์ฉ ์ค์ธ ์ด๋ฉ์ผ์
๋๋ค!'}), 409
elif 'username' in error_message:
return jsonify({'error': '์ด๋ฏธ ์ฌ์ฉ ์ค์ธ ์ฌ์ฉ์๋ช
์
๋๋ค!'}), 409
elif 'foreign key constraint' in error_message.lower():
return jsonify({'error': '์ฐธ์กฐํ๋ ๋ฐ์ดํฐ๊ฐ ์กด์ฌํ์ง ์์ต๋๋ค!'}), 400
elif 'check constraint' in error_message.lower():
return jsonify({'error': '์
๋ ฅ๊ฐ์ด ์ ํจํ์ง ์์ต๋๋ค!'}), 400
return jsonify({'error': '๋ฐ์ดํฐ๋ฒ ์ด์ค ์ค๋ฅ๊ฐ ๋ฐ์ํ์ต๋๋ค!'}), 500
except Exception as e:
return jsonify({'error': '์๋ฒ ์ค๋ฅ๊ฐ ๋ฐ์ํ์ต๋๋ค!'}), 500
โก ์ฑ๋ฅ ์ต์ ํ ํ
์ ์ฝ์กฐ๊ฑด์ ๋ฐ์ดํฐ ๋ฌด๊ฒฐ์ฑ์ ๋ณด์ฅํ์ง๋ง, ์๋ชป ์ฌ์ฉํ๋ฉด ์ฑ๋ฅ ๋ฌธ์ ๊ฐ ์๊ธธ ์ ์์ด. ์ค๋ฌด์์ ๊ผญ ์์์ผ ํ ์ต์ ํ ํ์ ์๋ ค์ค๊ฒ! ๐
โข FOREIGN KEY์ UNIQUE ์ ์ฝ์กฐ๊ฑด์ ์๋์ผ๋ก ์ธ๋ฑ์ค๋ฅผ ์์ฑํด
โข CHECK ์ ์ฝ์กฐ๊ฑด์ ์์ฃผ ์ฌ์ฉ๋๋ ์ปฌ๋ผ์ ๋ณ๋ ์ธ๋ฑ์ค ๊ณ ๋ ค
โข ๋ณตํฉ ์ ์ฝ์กฐ๊ฑด์ ๊ฒฝ์ฐ ์ปฌ๋ผ ์์๊ฐ ์ค์ํด (์ ํ๋๊ฐ ๋์ ์ปฌ๋ผ์ ์์!)
-- ์ข์ ์: ์ ํ๋๊ฐ ๋์ ์ปฌ๋ผ์ ์์
CREATE INDEX idx_order_search ON orders(status, customer_id, order_date);
-- ๋์ ์: ์ ํ๋๊ฐ ๋ฎ์ ์ปฌ๋ผ์ ์์
CREATE INDEX idx_order_bad ON orders(status, order_date, customer_id);
-- status๋ ๊ฐ์ ์ข
๋ฅ๊ฐ ์ ์ด์ ์ ํ๋๊ฐ ๋ฎ์!
๋๋์ ๋ฐ์ดํฐ๋ฅผ INSERTํ ๋๋ ์ผ์์ ์ผ๋ก ์ ์ฝ์กฐ๊ฑด์ ๋นํ์ฑํํ๋ฉด ์๋๊ฐ ๋นจ๋ผ์ ธ!
-- MySQL์์ ์ธ๋ํค ์ฒดํฌ ์์ ๋นํ์ฑํ
SET FOREIGN_KEY_CHECKS = 0;
-- ๋๋ ๋ฐ์ดํฐ ์ฝ์
INSERT INTO orders (customer_id, product_id, quantity)
SELECT customer_id, product_id, quantity
FROM temp_orders;
-- ์ธ๋ํค ์ฒดํฌ ๋ค์ ํ์ฑํ
SET FOREIGN_KEY_CHECKS = 1;
-- ์ ์ฝ์กฐ๊ฑด ์๋ฐ ๋ฐ์ดํฐ ํ์ธ
SELECT o.*
FROM orders o
LEFT JOIN customers c ON o.customer_id = c.customer_id
WHERE c.customer_id IS NULL;
ํธ๋ฆฌ๊ฑฐ๋ ํธ๋ฆฌํ์ง๋ง ์ฑ๋ฅ์ ์ํฅ์ ์ค ์ ์์ด. ๊ผญ ํ์ํ ๊ฒฝ์ฐ๋ง ์ฌ์ฉํ์!
-- ๋์ ์: ๋งค๋ฒ ์ ์ฒด ํ
์ด๋ธ ์ค์บ
CREATE TRIGGER update_product_rating
AFTER INSERT ON reviews
FOR EACH ROW
BEGIN
UPDATE products
SET average_rating = (
SELECT AVG(rating)
FROM reviews
WHERE product_id = NEW.product_id
)
WHERE product_id = NEW.product_id;
END;
-- ์ข์ ์: ์ฆ๋ถ ์
๋ฐ์ดํธ
CREATE TRIGGER update_product_rating_optimized
AFTER INSERT ON reviews
FOR EACH ROW
BEGIN
UPDATE products
SET
total_rating = total_rating + NEW.rating,
review_count = review_count + 1,
average_rating = (total_rating + NEW.rating) / (review_count + 1)
WHERE product_id = NEW.product_id;
END;
๋์ฉ๋ ํ ์ด๋ธ์ ํํฐ์ ๋์ ์ฌ์ฉํ๋ฉด ์ ์ฝ์กฐ๊ฑด ๊ฒ์ฌ ์๋๊ฐ ๋นจ๋ผ์ ธ!
-- ๋ ์ง ๊ธฐ๋ฐ ํํฐ์
๋
CREATE TABLE orders_partitioned (
order_id INT AUTO_INCREMENT,
customer_id INT NOT NULL,
order_date DATE NOT NULL,
total_amount DECIMAL(10, 2),
PRIMARY KEY (order_id, order_date),
FOREIGN KEY (customer_id) REFERENCES customers(customer_id)
)
PARTITION BY RANGE (YEAR(order_date)) (
PARTITION p2022 VALUES LESS THAN (2023),
PARTITION p2023 VALUES LESS THAN (2024),
PARTITION p2024 VALUES LESS THAN (2025),
PARTITION p_future VALUES LESS THAN MAXVALUE
);
๐ ์ค๋ฌด ๋ฒ ์คํธ ํ๋ํฐ์ค
๋ง์ง๋ง์ผ๋ก ์ค๋ฌด์์ ์ ๋ง ์ค์ํ ๋ฒ ์คํธ ํ๋ํฐ์ค๋ฅผ ์ ๋ฆฌํด๋ณผ๊ฒ! ์ด๊ฑด ๋ด๊ฐ ์ค์ ํ๋ก์ ํธ์์ ๋ฐฐ์ด ์์คํ ๊ฒฝํ๋ค์ด์ผ. ๐
1. ๋ช ํํ ๋ช ๋ช ๊ท์น ์ฌ์ฉ
โข pk_ํ ์ด๋ธ๋ช : PRIMARY KEY
โข fk_ํ ์ด๋ธ๋ช _์ฐธ์กฐํ ์ด๋ธ๋ช : FOREIGN KEY
โข uq_ํ ์ด๋ธ๋ช _์ปฌ๋ผ๋ช : UNIQUE
โข chk_ํ ์ด๋ธ๋ช _์กฐ๊ฑด๋ช : CHECK
โข idx_ํ ์ด๋ธ๋ช _์ปฌ๋ผ๋ช : INDEX
2. ๋ฌธ์ํ
โข ๊ฐ ์ ์ฝ์กฐ๊ฑด์ ๋ชฉ์ ๊ณผ ๋น์ฆ๋์ค ๊ท์น์ ์ฃผ์์ผ๋ก ๋ช ์
โข ERD(Entity Relationship Diagram)์ ์ ์ฝ์กฐ๊ฑด ํ์
โข ๋ฐ์ดํฐ ๋์ ๋๋ฆฌ ์์ฑ
3. ๋จ๊ณ์ ์ ์ฉ
โข ๊ฐ๋ฐ ํ๊ฒฝ์์ ๋จผ์ ํ ์คํธ
โข ์คํ ์ด์ง ํ๊ฒฝ์์ ์ฑ๋ฅ ๊ฒ์ฆ
โข ํ๋ก๋์ ๋ฐฐํฌ ์ ๋ชจ๋ํฐ๋ง
4. ๋ฒ์ ๊ด๋ฆฌ
โข ์คํค๋ง ๋ณ๊ฒฝ ์ด๋ ฅ์ Git์ผ๋ก ๊ด๋ฆฌ
โข ๋ง์ด๊ทธ๋ ์ด์ ์คํฌ๋ฆฝํธ ์์ฑ
โข ๋กค๋ฐฑ ๊ณํ ์๋ฆฝ
1. ๊ณผ๋ํ ์ ์ฝ์กฐ๊ฑด
โข ๋ชจ๋ ์ปฌ๋ผ์ CHECK ์ ์ฝ์กฐ๊ฑด์ ๊ฑธ์ง ๋ง์ธ์
โข ์ฑ๋ฅ๊ณผ ๋ฌด๊ฒฐ์ฑ์ ๊ท ํ์ ์ฐพ์ผ์ธ์
2. CASCADE ๋จ์ฉ
โข ON DELETE CASCADE๋ ์ ์คํ๊ฒ ์ฌ์ฉ
โข ์ค์ํ ๋ฐ์ดํฐ๋ RESTRICT ์ฌ์ฉ ๊ถ์ฅ
3. ์ ์ฝ์กฐ๊ฑด ์๋ ์ค๊ณ
โข "์ ํ๋ฆฌ์ผ์ด์ ์์ ๊ฒ์ฆํ๋๊น ๊ด์ฐฎ์"๋ ์ํํ ์๊ฐ!
โข ๋ฐ์ดํฐ๋ฒ ์ด์ค ๋ ๋ฒจ์ ๋ฌด๊ฒฐ์ฑ ๋ณด์ฅ์ ํ์
4. ํ ์คํธ ๋ถ์กฑ
โข ์ ์ฝ์กฐ๊ฑด ์ถ๊ฐ ํ ๋ฐ๋์ ํ ์คํธ
โข ์ฃ์ง ์ผ์ด์ค(๊ฒฝ๊ณ๊ฐ) ๊ฒ์ฆ ํ์
-- ์ข์ ์: ๋ช
ํํ ๋ช
๋ช
๊ณผ ์ฃผ์
CREATE TABLE products (
product_id INT AUTO_INCREMENT,
product_name VARCHAR(100) NOT NULL,
price DECIMAL(10, 2) NOT NULL,
discount_price DECIMAL(10, 2),
stock_quantity INT NOT NULL DEFAULT 0,
-- ๊ธฐ๋ณธํค: ์ํ ๊ณ ์ ์๋ณ์
CONSTRAINT pk_products PRIMARY KEY (product_id),
-- ๊ฐ๊ฒฉ ๊ฒ์ฆ: ์ ๊ฐ๋ 0๋ณด๋ค ์ปค์ผ ํจ
CONSTRAINT chk_products_price CHECK (price > 0),
-- ํ ์ธ๊ฐ ๊ฒ์ฆ: ํ ์ธ๊ฐ๋ ์ ๊ฐ๋ณด๋ค ๋ฎ์์ผ ํจ
CONSTRAINT chk_products_discount CHECK (
discount_price IS NULL OR
(discount_price > 0 AND discount_price < price)
),
-- ์ฌ๊ณ ๊ฒ์ฆ: ์ฌ๊ณ ๋ ์์์ผ ์ ์์
CONSTRAINT chk_products_stock CHECK (stock_quantity >= 0),
-- ์ํ๋ช
์ค๋ณต ๋ฐฉ์ง
CONSTRAINT uq_products_name UNIQUE (product_name)
) COMMENT='์ํ ์ ๋ณด ํ
์ด๋ธ - 2024.01 ์์ฑ';
๐ ์ค์ ๋๋ฒ๊น ๊ฐ์ด๋
์ ์ฝ์กฐ๊ฑด ๊ด๋ จ ์๋ฌ๊ฐ ๋ฐ์ํ์ ๋ ์ด๋ป๊ฒ ํด๊ฒฐํ ์ง ์์๋ณด์! ์ค๋ฌด์์ ์์ฃผ ๋ง์ฃผ์น๋ ์ํฉ๋ค์ด์ผ. ๐ง
๐ ์์ฃผ ๋ฐ์ํ๋ ์๋ฌ์ ํด๊ฒฐ๋ฒ
์์ธ: ๊ธฐ๋ณธํค ์ค๋ณต
ํด๊ฒฐ: AUTO_INCREMENT ์ฌ์ฉํ๊ฑฐ๋ ๊ณ ์ ํ ๊ฐ ์์ฑ
-- ๋ฌธ์ ์ํฉ
INSERT INTO users (user_id, username) VALUES (1, 'john');
INSERT INTO users (user_id, username) VALUES (1, 'jane'); -- โ ์๋ฌ!
-- ํด๊ฒฐ ๋ฐฉ๋ฒ 1: AUTO_INCREMENT ์ฌ์ฉ
CREATE TABLE users (
user_id INT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(50)
);
INSERT INTO users (username) VALUES ('john');
INSERT INTO users (username) VALUES ('jane'); -- โ
์๋์ผ๋ก 2 ํ ๋น
-- ํด๊ฒฐ ๋ฐฉ๋ฒ 2: UUID ์ฌ์ฉ
CREATE TABLE users (
user_id CHAR(36) PRIMARY KEY DEFAULT (UUID()),
username VARCHAR(50)
);
INSERT INTO users (username) VALUES ('john'); -- โ
์๋์ผ๋ก UUID ์์ฑ
์์ธ: ์ฐธ์กฐํ๋ ๋ถ๋ชจ ๋ฐ์ดํฐ๊ฐ ์์
ํด๊ฒฐ: ๋ถ๋ชจ ๋ฐ์ดํฐ ๋จผ์ ์์ฑํ๊ฑฐ๋ ์ธ๋ํค ๊ฐ ํ์ธ
-- ๋ฌธ์ ์ํฉ
INSERT INTO orders (order_id, customer_id, product_id)
VALUES (1, 999, 1); -- โ customer_id 999๊ฐ customers ํ
์ด๋ธ์ ์์!
-- ํด๊ฒฐ ๋ฐฉ๋ฒ 1: ๋ถ๋ชจ ๋ฐ์ดํฐ ๋จผ์ ํ์ธ
SELECT customer_id FROM customers WHERE customer_id = 999;
-- ๊ฒฐ๊ณผ๊ฐ ์์ผ๋ฉด ๋จผ์ ๊ณ ๊ฐ ์์ฑ
-- ํด๊ฒฐ ๋ฐฉ๋ฒ 2: ์กด์ฌํ๋ ๋ฐ์ดํฐ๋ง ์ฝ์
ํ๋ ์ฟผ๋ฆฌ
INSERT INTO orders (order_id, customer_id, product_id)
SELECT 1, c.customer_id, 1
FROM customers c
WHERE c.customer_id = 999;
-- ๊ณ ๊ฐ์ด ์์ผ๋ฉด ์๋ฌด๊ฒ๋ ์ฝ์
๋์ง ์์
-- ํด๊ฒฐ ๋ฐฉ๋ฒ 3: ์ธ๋ํค ์ ์ฝ์กฐ๊ฑด ํ์ธ ๋ฐ ์์
ALTER TABLE orders
DROP FOREIGN KEY fk_customer;
ALTER TABLE orders
ADD CONSTRAINT fk_customer
FOREIGN KEY (customer_id)
REFERENCES customers(customer_id)
ON DELETE RESTRICT
ON UPDATE CASCADE;
์์ธ: CHECK ์ ์ฝ์กฐ๊ฑด ์๋ฐ
ํด๊ฒฐ: ์ ๋ ฅ๊ฐ ๊ฒ์ฆ ๋๋ ์ ์ฝ์กฐ๊ฑด ์์
-- ๋ฌธ์ ์ํฉ
INSERT INTO employees (employee_id, name, age, salary)
VALUES (1, 'John', 15, 3000000); -- โ age < 18
-- ํด๊ฒฐ ๋ฐฉ๋ฒ 1: ์ฌ๋ฐ๋ฅธ ๊ฐ ์
๋ ฅ
INSERT INTO employees (employee_id, name, age, salary)
VALUES (1, 'John', 25, 3000000); -- โ
-- ํด๊ฒฐ ๋ฐฉ๋ฒ 2: ์ ์ฝ์กฐ๊ฑด ํ์ธ
SELECT CONSTRAINT_NAME, CHECK_CLAUSE
FROM INFORMATION_SCHEMA.CHECK_CONSTRAINTS
WHERE TABLE_NAME = 'employees';
-- ํด๊ฒฐ ๋ฐฉ๋ฒ 3: ํ์์ ์ ์ฝ์กฐ๊ฑด ์์
ALTER TABLE employees
DROP CHECK chk_age;
ALTER TABLE employees
ADD CONSTRAINT chk_age CHECK (age >= 16 AND age <= 70);
๐ ์ ์ฝ์กฐ๊ฑด ์๋ฐ ๋ฐ์ดํฐ ์ฐพ๊ธฐ
-- 1. ์ค๋ณต๋ ๋ฐ์ดํฐ ์ฐพ๊ธฐ (UNIQUE ์๋ฐ ๊ฐ๋ฅ์ฑ)
SELECT email, COUNT(*) as count
FROM users
GROUP BY email
HAVING COUNT(*) > 1;
-- 2. NULL ๊ฐ ์ฐพ๊ธฐ (NOT NULL ์๋ฐ ๊ฐ๋ฅ์ฑ)
SELECT *
FROM products
WHERE product_name IS NULL OR price IS NULL;
-- 3. ์ฐธ์กฐ ๋ฌด๊ฒฐ์ฑ ์๋ฐ ์ฐพ๊ธฐ (FOREIGN KEY ์๋ฐ ๊ฐ๋ฅ์ฑ)
SELECT o.*
FROM orders o
LEFT JOIN customers c ON o.customer_id = c.customer_id
WHERE c.customer_id IS NULL;
-- 4. CHECK ์ ์ฝ์กฐ๊ฑด ์๋ฐ ๊ฐ๋ฅ์ฑ ์ฐพ๊ธฐ
SELECT *
FROM employees
WHERE age < 18 OR age > 70 OR salary <= 0;
-- 5. ๋ฒ์๋ฅผ ๋ฒ์ด๋ ๋ฐ์ดํฐ ์ฐพ๊ธฐ
SELECT *
FROM products
WHERE discount_price >= price -- ํ ์ธ๊ฐ๊ฐ ์ ๊ฐ๋ณด๋ค ๋๊ฑฐ๋ ๊ฐ์
OR stock_quantity < 0; -- ์ฌ๊ณ ๊ฐ ์์
๐ ๋ง๋ฌด๋ฆฌํ๋ฉฐ
์! ์ฌ๊ธฐ๊น์ง ์ฝ์๋ค๋ฉด ์ ๋ง ๋๋จํด! ๐
๋ฐ์ดํฐ ๋ฌด๊ฒฐ์ฑ๊ณผ ์ ์ฝ์กฐ๊ฑด์ ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ค๊ณ์ ํต์ฌ์ด์ผ. ์ฒ์์๋ ๋ณต์กํ๊ณ ๊ท์ฐฎ๊ฒ ๋๊ปด์ง ์ ์์ง๋ง, ์ ๋๋ก ์ค์ ํด๋๋ฉด:
โ
๋ฐ์ดํฐ ํ์ง์ด ํฅ์๋ผ
โ
๋ฒ๊ทธ๊ฐ ์ค์ด๋ค์ด
โ
์ ์ง๋ณด์๊ฐ ์ฌ์์ ธ
โ
์ ๋ขฐ์ฑ ์๋ ์์คํ
์ ๋ง๋ค ์ ์์ด
๊ธฐ์ตํด! ์ ์ฝ์กฐ๊ฑด์ ๊ท์ฐฎ์ ๊ฒ ์๋๋ผ ๋ฏธ๋์ ๋๋ฅผ ๋์์ฃผ๋ ์น๊ตฌ์ผ! ๐
1๏ธโฃ ๊ธฐ์ด: PRIMARY KEY, FOREIGN KEY, NOT NULL ์๋ฒฝํ ์ดํด
2๏ธโฃ ์ค๊ธ: UNIQUE, CHECK, DEFAULT ํ์ฉ
3๏ธโฃ ๊ณ ๊ธ: ํธ๋ฆฌ๊ฑฐ, ์ ์ฅ ํ๋ก์์ , ๋ณตํฉ ์ ์ฝ์กฐ๊ฑด
4๏ธโฃ ์ค์ : ์ฑ๋ฅ ์ต์ ํ, ์๋ฌ ์ฒ๋ฆฌ, ๋ฒ ์คํธ ํ๋ํฐ์ค
๋ฐ์ดํฐ๋ฒ ์ด์ค ์ค๊ณ๋ ์ ์ฝ์กฐ๊ฑด ๊ตฌํ์ด ์ด๋ ต๋ค๋ฉด, ์ฌ๋ฅ๋ท(https://www.jaenung.net)์์ ์ ๋ฌธ๊ฐ์ ๋์์ ๋ฐ์๋ณด๋ ๊ฒ๋ ์ข์ ๋ฐฉ๋ฒ์ด์ผ! ์ค๋ฌด ๊ฒฝํ์ด ํ๋ถํ ๊ฐ๋ฐ์๋ค์ด ํ๋ก์ ํธ์ ์ต์ ํ๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ค๊ณ๋ฅผ ๋์์ค ๊ฑฐ์ผ. ๐
์ด์ ๋๋ ๋ฐ์ดํฐ ๋ฌด๊ฒฐ์ฑ ๋ง์คํฐ! ๐ช
์ค์ ํ๋ก์ ํธ์์ ๋ฐฐ์ด ๋ด์ฉ์ ์ ์ฉํด๋ณด๊ณ , ๊ณ์ ์ฐ์ตํ๋ฉด์ ์ค๋ ฅ์ ํค์๋๊ฐ์!
๊ถ๊ธํ ์ ์ด ์๊ฑฐ๋ ๋ ์๊ณ ์ถ์ ๋ด์ฉ์ด ์๋ค๋ฉด ์ธ์ ๋ ์ง๋ฌธํด์ค.
ํจ๊ป ์ฑ์ฅํ๋ ๊ฐ๋ฐ์๊ฐ ๋์! ๐ฑโจ
๊ด๋ จ ํค์๋
๋๊ธ ์์ฑ
์ด ๊ธ์ ๋ํ ์ฌ๋ฌ๋ถ์ ์๊ฐ์ ๋ค๋ ค์ฃผ์ธ์
๋ก๊ทธ์ธ์ด ํ์ํฉ๋๋ค
๋๊ธ์ ์์ฑํ๋ ค๋ฉด ๋จผ์ ๋ก๊ทธ์ธํด์ฃผ์ธ์.
๋๊ธ 0
์ง์์ธ์ ์ฒ - ์ง์ ์ฌ์ฐ๊ถ ๋ณดํธ ๊ณ ์ง
์ง์ ์ฌ์ฐ๊ถ ๋ณดํธ ๊ณ ์ง
- ์ ์๊ถ ๋ฐ ์์ ๊ถ: ๋ณธ ์ปจํ ์ธ ๋ ์ฌ๋ฅ๋ท์ ๋ ์ AI ๊ธฐ์ ๋ก ์์ฑ๋์์ผ๋ฉฐ, ๋ํ๋ฏผ๊ตญ ์ ์๊ถ๋ฒ ๋ฐ ๊ตญ์ ์ ์๊ถ ํ์ฝ์ ์ํด ๋ณดํธ๋ฉ๋๋ค.
- AI ์์ฑ ์ปจํ ์ธ ์ ๋ฒ์ ์ง์: ๋ณธ AI ์์ฑ ์ปจํ ์ธ ๋ ์ฌ๋ฅ๋ท์ ์ง์ ์ฐฝ์๋ฌผ๋ก ์ธ์ ๋๋ฉฐ, ๊ด๋ จ ๋ฒ๊ท์ ๋ฐ๋ผ ์ ์๊ถ ๋ณดํธ๋ฅผ ๋ฐ์ต๋๋ค.
- ์ฌ์ฉ ์ ํ: ์ฌ๋ฅ๋ท์ ๋ช ์์ ์๋ฉด ๋์ ์์ด ๋ณธ ์ปจํ ์ธ ๋ฅผ ๋ณต์ , ์์ , ๋ฐฐํฌ, ๋๋ ์์ ์ ์ผ๋ก ํ์ฉํ๋ ํ์๋ ์๊ฒฉํ ๊ธ์ง๋ฉ๋๋ค.
- ๋ฐ์ดํฐ ์์ง ๊ธ์ง: ๋ณธ ์ปจํ ์ธ ์ ๋ํ ๋ฌด๋จ ์คํฌ๋ํ, ํฌ๋กค๋ง, ๋ฐ ์๋ํ๋ ๋ฐ์ดํฐ ์์ง์ ๋ฒ์ ์ ์ฌ์ ๋์์ด ๋ฉ๋๋ค.
- AI ํ์ต ์ ํ: ์ฌ๋ฅ๋ท์ AI ์์ฑ ์ปจํ ์ธ ๋ฅผ ํ AI ๋ชจ๋ธ ํ์ต์ ๋ฌด๋จ ์ฌ์ฉํ๋ ํ์๋ ๊ธ์ง๋๋ฉฐ, ์ด๋ ์ง์ ์ฌ์ฐ๊ถ ์นจํด๋ก ๊ฐ์ฃผ๋ฉ๋๋ค.
์์ง ๋๊ธ์ด ์์ต๋๋ค.