Post

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

  1. FOREIGN KEY는 을에 적는다.
    ❓ 을이란: optional인 관계, many가 을
  2. NOT NULL
    optional을 나타낼 수 있다.
  3. UNIQUE
    UNIQUE 사용유무로 1:1과 1:N 을 구별할 수 있다.

☑️ 1:1

스크린샷 2024-01-03 오후 4 51 42

  • 한 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

스크린샷 2024-01-03 오후 4 53 37

  • 하나의 책은 여러 리뷰를 가질 수 있다.
  • 리뷰는 하나의 책을 가져야 한다.
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

스크린샷 2024-01-03 오후 4 55 38

  • 한 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

참조 무결성
데이터 간 항상 일관된 값/관계가 유지되어야 한다.

  1. FK가 참조하는 table의 순서가 맞지 않으면 생성, 삭제 실패
  2. 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는 을에 적는다고 했다.

테이블끼리 서로서로 참조하면 안되나?
갑, 을 모두 서로 적으면 안되나?

  1. 우선, 만드는 것부터 힘듦.
    참조되는 테이블부터 만들어야 하는데, 이 테이블도 다른 테이블을 참조하려면 누구부터 만들라는겨..
    우선 테이블 하나 만들고 나중에 다른 테이블을 참조하도록 수정해야 함.
  2. 서로 참조하면, 이제 삭제하거나 업데이트 할 때 제약이 많음.
  3. 만약 cascade까지 되어있다면, 이 테이블에서 삭제하면 다른 테이블에서도 다 삭제됨!!! 대참사!

    따라서 두 테이블 간 한 테이블에게만 FK를 주게 되었다.
    ‘갑’인 테이블을 참조하도록 ‘을’관계인 테이블에게 FK를 준다.

근데 두 테이블 간 갑, 을이 없으면요?
두 테이블이 N:M 관계라 갑, 을이 명확하지 않으면
➡️ 둘 중 아무나 한 개를 정해서 FK를 준다.
절대 서로 참조하지는 않는다.

This post is licensed under CC BY 4.0 by the author.