6. 관계와 제약조건

1.관계란?

관계는 여러 테이블에 분산 저장된 데이터가 서로 어떻게 연결돼 있는지를 정의하는 개념이다.

테이블이 서로 관련 있는 데이터를 묶은 것이라면, 관계는 여러 테이블에 흩어져 있는 데이터 간 연결고리를 맺어주는 것이다.

관계는 크게 일대일(1:1), 일대다(1:N), 다대다(N:M) 관계로 나뉜다.

 

1.1 일대일(1:1) 관계

하나의 데이터가 하나의 데이터와만 연결된 관계이다.

A 테이블의 한 튜플이 B 테이블의 특정 튜플과 1:1로 매칭될 때 일대일 관계 라고 한다.

 

ex) 사용자(User)와 프로필(Profile) 테이블

CREATE TABLE User (
    user_id INT PRIMARY KEY,
    username VARCHAR(50) NOT NULL
);

CREATE TABLE Profile (
    profile_id INT PRIMARY KEY,
    user_id INT UNIQUE,
    bio TEXT,
    FOREIGN KEY (user_id) REFERENCES User(user_id)
);

 

- Profile 테이블의 user_idUser 테이블의 user_id를 참조하는 외래키(FK)이다.

- UNIQUE 제약 조건을 사용하여 한 사용자가 하나의 프로필만 가지도록 설정한다.

 

1.2 일대다(1:N) 관계

하나의 데이터가 여러 데이터와 연결된 관계이다.

A 테이블의 한 튜플이 B 테이블의 여러 튜플과 연결된다면 일대다 관계라고 한다.

 

ex) 사용자(User)와 게시글(Post) 테이블

CREATE TABLE User (
    user_id INT PRIMARY KEY,
    username VARCHAR(50) NOT NULL
);

CREATE TABLE Post (
    post_id INT PRIMARY KEY,
    user_id INT,
    title VARCHAR(100) NOT NULL,
    content TEXT,
    FOREIGN KEY (user_id) REFERENCES User(user_id)
);

 

- Post 테이블의 user_id가 User 테이블의 user_id를 참조하는 외래키(FK) 이다.

- 한 사용자가 여러 개의 게시글을 작성할 수 있도록 설계되었다.

 

1.3 다대다(N:M) 관계

여러 데이터가 여러 데이터와 연결된 관계이다.

다대다 관계를 구현하기 위해서는 중간 테이블을 사용한다.

 

ex) 학생(Student)과 강의(Course) 테이블

CREATE TABLE Student (
    student_id INT PRIMARY KEY,
    name VARCHAR(50) NOT NULL
);

CREATE TABLE Course (
    course_id INT PRIMARY KEY,
    course_name VARCHAR(100) NOT NULL
);

CREATE TABLE Enrollment (
    student_id INT,
    course_id INT,
    PRIMARY KEY (student_id, course_id),
    FOREIGN KEY (student_id) REFERENCES Student(student_id),
    FOREIGN KEY (course_id) REFERENCES Course(course_id)
);

 

- Enrollment 테이블은 Student와 Course의 관계를 연결하는 중간 테이블이다.

- 복합 기본키(PK)를 사용해 student_id와 course_id가 동시에 중복되지 않도록 설정한다.

- 이를 통해 한 학생이 여러 강의를 수강할 수 있고, 한 강의에 여러 학생이 등록될 수 있다.

 

 

2. 기본키(PK)와 외래키(FK)

2.1 기본키(Primary Key, PK)

테이블 내에서 모든 튜플을 유일하게 식별할 수 있는 칼럼 또는 칼럼 조합이다.

 

특징:

- 유일성(Unique): 같은 값을 가지는 행이 존재할 수 없다.

- 비 NULL(Not Null): 반드시 값이 존재해야 한다.

- 불변성(Immutability): 한 번 지정된 값은 변경되지 않는다.

 

2.2 외래키(Foreign Key, FK)

다른 테이블의 기본키를 참조하는 칼럼이다.

 

특징:

- 참조 무결성: 참조하는 값이 부모 테이블에 존재해야 한다.

- NULL 허용 가능: 특정 데이터가 관계를 맺지 않을 경우 NULL 값을 가질 수 있다.

 

사용방법:

FOREIGN KEY (칼럼명) REFERENCES 연결대상_테이블(연결대상_테이블_기본키)

 

 

3. 제약조건(Constraints)

테이블의 칼럼 값에 대한 제한이나 규칙을 정의한다.

 

제약조건 설명
AUTO_INCREMENT 숫자형 칼럼의 값을 자동 증가
UNIQUE 중복된 값을 허용하지 않음
NOT NULL NULL 값을 허용하지 않음
DEFAULT 입력 값이 없을 때 기본값 설정
CHECK 특정 조건을 만족해야 함
UNSIGNED 음수를 허용하지 않고 양수만 저장

 

 

ex) CHECK 제약조건 사용

CREATE TABLE Product (
    product_id INT PRIMARY KEY,
    price DECIMAL(10,2) CHECK (price > 0)
);

 

- price 칼럼은 0보다 큰 값만 허용됨

 

 

4. 관계 설정 요약

관계 유형 설명 외래키 위치
일대다(1:N) 한 레코드가 여러 레코드와 매칭 다쪽(많은 데이터가 있는 테이블)
다대다(N:M) 여러 레코드가 여러 레코드와 매칭 중간 테이블 사용
일대일(1:1) 한 레코드가 다른 테이블의 한 레코드와 매칭 선택적 (더 적은 사용 빈도 쪽)

 

 

ex) 온라인 쇼핑몰 데이터베이스

 

1) 일대일(1:1) 관계:

 - 각 고객(Customer)은 하나의 기본 배송 주소(ShippingAddress)를 가진다.


2) 일대다(1:N) 관계:
 - 한 고객(Customer)은 여러 주문(Orders)을 할 수 있다.
 - 한 상품(Product)은 여러 리뷰(Review)를 받을 수 있다.


3) 다대다(N:M) 관계:

 - 여러 주문(Orders)에 여러 상품(Product)이 포함될 수 있으며, 이는 OrderItem 중간 테이블을 통해 구현된다.

 

/* 사용자 테이블 */
CREATE TABLE Customer (
    customer_id INT PRIMARY KEY AUTO_INCREMENT,
    email VARCHAR(100) UNIQUE NOT NULL,
    password VARCHAR(255) NOT NULL,
    name VARCHAR(100) NOT NULL,
    registration_date DATETIME DEFAULT CURRENT_TIMESTAMP
);

/* 배송 주소 테이블 (일대일 관계) */
CREATE TABLE ShippingAddress (
    address_id INT PRIMARY KEY AUTO_INCREMENT,
    customer_id INT UNIQUE,
    address_line1 VARCHAR(200) NOT NULL,
    address_line2 VARCHAR(200),
    city VARCHAR(100) NOT NULL,
    state VARCHAR(100),
    postal_code VARCHAR(20) NOT NULL,
    country VARCHAR(100) NOT NULL,
    is_default BOOLEAN DEFAULT TRUE,
    FOREIGN KEY (customer_id) REFERENCES Customer(customer_id) ON DELETE CASCADE
);

/* 주문 테이블 (일대다 관계) */
CREATE TABLE Orders (
    order_id INT PRIMARY KEY AUTO_INCREMENT,
    customer_id INT NOT NULL,
    order_date DATETIME DEFAULT CURRENT_TIMESTAMP,
    status ENUM('pending', 'processing', 'shipped', 'delivered', 'cancelled') DEFAULT 'pending',
    total_amount DECIMAL(10, 2) NOT NULL,
    FOREIGN KEY (customer_id) REFERENCES Customer(customer_id) ON DELETE RESTRICT
);

/* 상품 테이블 */
CREATE TABLE Product (
    product_id INT PRIMARY KEY AUTO_INCREMENT,
    name VARCHAR(200) NOT NULL,
    description TEXT,
    price DECIMAL(10, 2) NOT NULL CHECK (price > 0),
    stock_quantity INT NOT NULL DEFAULT 0,
    category VARCHAR(100)
);

/* 주문 상세 테이블 (다대다 관계를 위한 중간 테이블) */
CREATE TABLE OrderItem (
    order_id INT,
    product_id INT,
    quantity INT NOT NULL CHECK (quantity > 0),
    price_at_time DECIMAL(10, 2) NOT NULL,
    PRIMARY KEY (order_id, product_id),
    FOREIGN KEY (order_id) REFERENCES Orders(order_id) ON DELETE CASCADE,
    FOREIGN KEY (product_id) REFERENCES Product(product_id) ON DELETE RESTRICT
);

/* 상품 리뷰 테이블 (일대다 관계) */
CREATE TABLE Review (
    review_id INT PRIMARY KEY AUTO_INCREMENT,
    product_id INT NOT NULL,
    customer_id INT NOT NULL,
    rating INT NOT NULL CHECK (rating BETWEEN 1 AND 5),
    comment TEXT,
    review_date DATETIME DEFAULT CURRENT_TIMESTAMP,
    FOREIGN KEY (product_id) REFERENCES Product(product_id) ON DELETE CASCADE,
    FOREIGN KEY (customer_id) REFERENCES Customer(customer_id) ON DELETE CASCADE
);

 

 

'학습 > DB' 카테고리의 다른 글

8. 그룹화, 정렬, 제한  (0) 2025.03.06
7. 조인(JOIN)  (0) 2025.03.01
5. 자료형과 필터링  (1) 2025.02.23
4. 집계 함수 및 데이터 처리  (0) 2025.02.21
3. SQL 데이터 필터링과 연산자 정리  (0) 2025.02.20