RDB Table 관계
✅ 관계형 데이터 베이스 특징
relation ➕
key-value
➕ constraint
☑️ Optionality 관계의 선택성
Mandatory( ) 🆚 Optional (O)
두 테이블 간 관계 설정 시, 페어링 필수 여부
관계의 중요성과 비슷한 의미
예를 들어 부모는 자식을 가질 수도, 안 가질 수도 있지만
자식은 꼭 부모를 가져야 한다.
- 부모는 자식을 가질 수 있다. O
자식은 부모를 가져야 한다.
☑️ Cardinality 관계의 기수성
One(0 또는 1) 🆚 Many (0이상 또는 1이상)
두 테이블 간 관계 설정 시, 참여 멤버 수 표현z
관계의 다중성과 비슷한 의미
부모는 자식을 여러명 가질 수 있지만,
자식은 부모를 여러명 가질 수 없음
- 부모는 여러 자식들을 가질 수 있다.
- 자식은 한 부모를 가져야 한다.
✅ PRIMARY KEY
기본 키
- NOT NULL
- UNIQUE 다른 row와 중복될 수 없다, 단일 키
✅ FOREIGN KEY
다른 테이블의 PRIMARY KEY, UNIQUE 필드와 대응하여 테이블 간의 참조 관계를 표현하는 속성
FK는 ‘을’관계인 테이블에 적는다.
1
2
FOREIGN KEY(customer_id) PREFERENCES customer(customer_id)
FOREIGN KEY(현재 테이블의 필드) PREFERENCES 그 테이블명(그 테이블의 필드)
✅ RDB Table 관계
💡 RDB Table TIP
- FOREIGN KEY는 을에 적는다.
❓ 을이란: optional인 관계, many가 을 - NOT NULL
optional을 나타낼 수 있다. - UNIQUE
UNIQUE 사용유무로 1:1과 1:N 을 구별할 수 있다.
☑️ 1:1
- 한 user는 하나의 address만 가질 수 있다.
- 한 address는 하나의 user를 가져야 한다.
그러니까 user이 갑이고, address가 을이다.
FOREIGN KEY는 을에 적는다.
따라서 address에 FOREIGN KEY 적는다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
CREATE TABLE users(
id INT AUTO_INCREMENT PRIMARY KEY,
user_name VARCHAR(50),
enabled Boolean
);
CREATE TABLE address(
addr_id INT AUTO_INCREMENT PRIMARY KEY,
user_id INT UNIQUE NOT NULL, -- 1:1
street VARCHAR(100),
city VARCHAR(50),
state VARCHAR(50),
FOREIGN KEY(user_id) REFERENCES users(id)
);
--DDL
--CREATE TABLE `address` (
-- `addr_id` int NOT NULL AUTO_INCREMENT,
-- `user_id` int NOT NULL,
-- `street` varchar(100) DEFAULT NULL,
-- `city` varchar(50) DEFAULT NULL,
-- `state` varchar(50) DEFAULT NULL,
-- PRIMARY KEY (`addr_id`),
-- UNIQUE KEY `user_id` (`user_id`),
-- CONSTRAINT `address_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`)
--) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
☑️ 1:N
- 하나의 책은 여러 리뷰를 가질 수 있다.
- 리뷰는 하나의 책을 가져야 한다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
CREATE TABLE book(
id INT AUTO_INCREMENT PRIMARY KEY,
book_name VARCHAR(50) NOT NULL,
author VARCHAR(50) NOT NULL,
content LONGTEXT
);
CREATE TABLE review(
reviews_id INT AUTO_INCREMENT PRIMARY KEY,
book_id INT NOT NULL, -- 1:N thus, does not need to be unique
user_name VARCHAR(30),
content MEDIUMTEXT,
FOREIGN KEY(book_id) REFERENCES book(id)
);
☑️ N:M
- 한 user는 여러 책을 살 수 있다.
- 한 책은 여러 user에게 판매될 수 있다.
그런데 N:M을 두면 중복 문제가 많이 생겨서 연결 테이블(mapping table)을 두는 것이 일반적이다.
1
2
3
4
5
6
7
8
9
10
-- mapping table
CREATE TABLE users_book_purchase( -- mappingTable
id INT AUTO_INCREMENT PRIMARY KEY,
book_id INT NOT NULL, -- 1:N, thus not unique
user_id INT NOT NULL, -- 1:N
purchase_date DATETIME NOT NULL,
price INT,
FOREIGN KEY(user_id) REFERENCES users(id),
FOREIGN KEY(book_id) REFERENCES book(id)
);
📌 Referential Integrity Constraint
참조 무결성
데이터 간 항상 일관된 값/관계가 유지되어야 한다.
- FK가 참조하는 table의 순서가 맞지 않으면 생성, 삭제 실패
- FK가 참조하는 값이 없으면 insert 실패
💥 table A를 참조하는 table B가 있는데 table A를 삭제해버리면 실행 안 된다. ❌
📌 Betalock
- for data referential integrity
certain constraints to keep integrity
- If in RDB foreign key does not exist ➡️ betalock
⚠️ 테이블 간 상호참조는 지양
FOREIGN KEY는 을에 적는다고 했다.
❓ 테이블끼리 서로서로 참조하면 안되나?
갑, 을 모두 서로 적으면 안되나?
- 우선, 만드는 것부터 힘듦.
참조되는 테이블부터 만들어야 하는데, 이 테이블도 다른 테이블을 참조하려면 누구부터 만들라는겨..
우선 테이블 하나 만들고 나중에 다른 테이블을 참조하도록 수정해야 함. - 서로 참조하면, 이제 삭제하거나 업데이트 할 때 제약이 많음.
- 만약 cascade까지 되어있다면, 이 테이블에서 삭제하면 다른 테이블에서도 다 삭제됨!!! 대참사!
따라서 두 테이블 간 한 테이블에게만 FK를 주게 되었다.
‘갑’인 테이블을 참조하도록 ‘을’관계인 테이블에게 FK를 준다.
❓ 근데 두 테이블 간 갑, 을이 없으면요?
두 테이블이 N:M 관계라 갑, 을이 명확하지 않으면
➡️ 둘 중 아무나 한 개를 정해서 FK를 준다.
절대 서로 참조하지는 않는다.
This post is licensed under CC BY 4.0 by the author.