DBGuide

테이블 관계 — 1:1, 1:N, N:M

📖 약 2🏷 스키마 설계

테이블 관계의 종류

현실의 데이터는 서로 연관되어 있습니다. 테이블 간의 관계는 세 가지로 분류합니다.

1:1 관계 (One-to-One)

한 행이 다른 테이블의 정확히 한 행과 대응됩니다.

-- 사용자와 프로필 (분리 이유: 자주 조회하지 않는 데이터 분리)
CREATE TABLE users (
    id    SERIAL PRIMARY KEY,
    email VARCHAR(255) UNIQUE NOT NULL
);

CREATE TABLE user_profiles (
    user_id    INT PRIMARY KEY REFERENCES users(id) ON DELETE CASCADE,
    bio        TEXT,
    avatar_url VARCHAR(500),
    birth_date DATE
);

1:1 관계는 보안(민감 데이터 분리), 성능(자주 안 쓰는 컬럼 분리), 선택적 데이터 표현에 사용합니다.

1:N 관계 (One-to-Many)

가장 흔한 관계입니다. 한 행이 다른 테이블의 여러 행과 대응됩니다.

-- 부서 1 : 직원 N
CREATE TABLE departments (
    id   SERIAL PRIMARY KEY,
    name VARCHAR(100) NOT NULL
);

CREATE TABLE employees (
    id            SERIAL PRIMARY KEY,
    name          VARCHAR(100) NOT NULL,
    department_id INT REFERENCES departments(id)  -- FK가 N쪽에 위치
);
-- 게시글 1 : 댓글 N
CREATE TABLE posts (
    id         SERIAL PRIMARY KEY,
    title      VARCHAR(300) NOT NULL,
    created_at TIMESTAMP DEFAULT NOW()
);

CREATE TABLE comments (
    id         SERIAL PRIMARY KEY,
    post_id    INT NOT NULL REFERENCES posts(id) ON DELETE CASCADE,
    body       TEXT NOT NULL,
    created_at TIMESTAMP DEFAULT NOW()
);

외래키는 항상 N쪽 테이블에 위치합니다.

N:M 관계 (Many-to-Many)

양쪽 테이블의 행이 서로 여러 개와 대응됩니다. 중간 테이블(junction table) 로 구현합니다.

-- 학생 N : 수업 M
CREATE TABLE students (
    id   SERIAL PRIMARY KEY,
    name VARCHAR(100) NOT NULL
);

CREATE TABLE courses (
    id   SERIAL PRIMARY KEY,
    name VARCHAR(200) NOT NULL
);

-- 중간 테이블
CREATE TABLE enrollments (
    student_id INT REFERENCES students(id) ON DELETE CASCADE,
    course_id  INT REFERENCES courses(id)  ON DELETE CASCADE,
    enrolled_at TIMESTAMP DEFAULT NOW(),
    grade       CHAR(2),
    PRIMARY KEY (student_id, course_id)  -- 복합 기본키로 중복 방지
);

JOIN으로 관계 데이터 조회

-- 학생별 수강 과목 목록
SELECT
    s.name AS student_name,
    c.name AS course_name,
    e.grade
FROM students s
JOIN enrollments e ON s.id = e.student_id
JOIN courses    c ON c.id = e.course_id
ORDER BY s.name, c.name;

ON DELETE 옵션

옵션 부모 행 삭제 시 동작
CASCADE 자식 행도 함께 삭제
RESTRICT 자식 행이 있으면 삭제 거부 (기본값)
SET NULL 자식의 FK를 NULL로 설정
SET DEFAULT 자식의 FK를 기본값으로 설정

댓글

... 으로 작성됩니다

댓글을 불러오는 중...