다대다 관계를 푸는 표준적인 해법은 중간에 새로운 테이블을 하나 만드는 것이다. 이 테이블을 보통 다음과 같이 부른다.
핵심 아이디어는 간단하다.
"다대다(M:N) 관계를 두 개의 일대다(1:N, N:1) 관계로 분해한다."
쇼핑몰 예시에서, orders와 product 사이에 order_product라는 연결 테이블을 만든다.
orders (M) <-----> (N) product
==> 연결 테이블 추가 후
orders (1) <-----> (N) order_product (N) <-----> (1) product
이제 의미는 이렇게 바뀐다.
orders)은 여러 주문 상품(order_product)을 가진다. → 1:Nproduct)은 여러 주문 상품(order_product)에 포함될 수 있다. → 1:N다음은 product, orders, order_product 세 테이블을 사용하는 예시다.
-- 상품 테이블
CREATE TABLE product (
product_id BIGINT PRIMARY KEY,
name VARCHAR(100) NOT NULL,
price INT NOT NULL
);
-- 주문 테이블
CREATE TABLE orders (
order_id BIGINT PRIMARY KEY,
orderer_id BIGINT NOT NULL,
ordered_at DATETIME NOT NULL
);
-- 주문-상품 연결 테이블
CREATE TABLE order_product (
order_product_id BIGINT PRIMARY KEY,
order_id BIGINT NOT NULL,
product_id BIGINT NOT NULL,
order_price INT NOT NULL, -- 주문 당시 가격
quantity INT NOT NULL, -- 주문 수량
CONSTRAINT fk_order_product_order
FOREIGN KEY (order_id) REFERENCES orders(order_id),
CONSTRAINT fk_order_product_product
FOREIGN KEY (product_id) REFERENCES product(product_id)
);
샘플 데이터까지 넣어서 보면 더 직관적이다.
-- product
INSERT INTO product (product_id, name, price) VALUES
(101, '기계식 키보드', 135000),
(102, '무소음 마우스', 45000),
(103, '4K 모니터', 350000);
-- orders
INSERT INTO orders (order_id, orderer_id, ordered_at) VALUES
(1001, 1, '2025-08-06'),
(1002, 3, '2025-08-07'),
(1003, 1, '2025-08-08'),
(1004, 2, '2025-08-08');
-- order_product (연결 테이블)
INSERT INTO order_product
(order_product_id, order_id, product_id, order_price, quantity) VALUES
(201, 1001, 101, 120000, 2),
(202, 1001, 102, 45000, 1),
(203, 1002, 103, 350000, 1),
(204, 1003, 102, 45000, 1),
(205, 1004, 101, 135000, 1),
(206, 1004, 103, 350000, 1);
이를 표로 나타내면 다음과 같다.
product