최원종의 개발 블로그

PRIMARY KEY, UNIQUE, FOREIGN KEY - 10 본문

MySQL

PRIMARY KEY, UNIQUE, FOREIGN KEY - 10

chl6698 2026. 4. 3. 12:39

키 제약 조건이란?

데이터 무결성(데이터가 정확하고 일관되게 유지되는 것)을 보장하기 위한 규칙을 말함

비유: 학교 학생증

  PK     = 학번 (전교에서 절대 겹칠 수 없음, 비워둘 수 없음)
  UNIQUE = 이메일 (각자 달라야 함, 학번과 달리 없을 수도 있음)
  FK     = 소속 학과 코드 (학교에 실제 존재하는 학과만 쓸 수 있음)


PRIMARY KEY (기본 키)

역할: 테이블의 각 행을 고유하게 식별
특징:
  - 중복 값 불가
  - NULL 불가
  - 테이블당 하나만 설정 가능
  - 자동으로 인덱스 생성 → 조회 빠름
-- 방법 1: 컬럼 뒤에 바로 선언
CREATE TABLE student2 (
    student_id INT PRIMARY KEY,
    name       VARCHAR(50) NOT NULL
);


-- 방법 2: 테이블 끝에 선언 (복합 PK 등에 사용)
CREATE TABLE student3 (
    student_id INT,
    name       VARCHAR(50) NOT NULL,
    PRIMARY KEY (student_id)
);

-- 1. 테이블 하단에 PRIMARY KEY(컬럼1, 컬럼2) 형태

    
-- 수강신청 정보를 저장하는 테이블
CREATE TABLE enrollment (
    student_id INT,          -- 학번
    course_id  VARCHAR(10),  -- 과목코드 (예: 'CS101')
    reg_date   DATE,         -- 신청 날짜
    PRIMARY KEY (student_id, course_id)
);

-- [핵심] 두 컬럼을 묶어서 기본키로 설정
-- 이 조합은 테이블 전체에서 유일해야 함!

 


UNIQUE KEY (고유 키)

역할: 특정 컬럼의 값이 중복되지 않도록 보장
특징:
  - 중복 값 불가
  - NULL 은 여러 개 허용 (MySQL 기준)
  - 테이블에 여러 개 설정 가능
  - 자동으로 인덱스 생성
CREATE TABLE member (
    id    INT          PRIMARY KEY AUTO_INCREMENT,
    email VARCHAR(100) UNIQUE,       -- 이메일은 중복 불가
    name  VARCHAR(50)  NOT NULL,
    phone VARCHAR(20)  UNIQUE        -- 전화번호도 중복 불가
);

CREATE TABLE member2 (
    id    INT PRIMARY KEY,
    email VARCHAR(100) UNIQUE,       -- 이메일은 중복 불가
    name  VARCHAR(50)  NOT NULL,
    phone VARCHAR(20)  UNIQUE        -- 전화번호도 중복 불가
);

FOREIGN KEY (외래 키)

역할: 다른 테이블의 PK 를 참조하여 관계 형성
특징:
  - 참조하는 값은 상대 테이블에 반드시 존재해야 함
  - NULL 허용 가능
  - 데이터 무결성 보장
CREATE TABLE orders (
    id        INT  PRIMARY KEY AUTO_INCREMENT,
    member_id INT  NOT NULL,
    amount    INT  NOT NULL,
    FOREIGN KEY (member_id) REFERENCES member(id)
    -- orders.member_id 는 member.id 에 있는 값만 가능
);

 


세 가지 키 비교

  PRIMARY KEY  UNIQUE KEY  FOREIGN KEY
역할 행 고유 식별 중복 값 방지 테이블 간 관계
중복 불가 불가 가능
NULL 불가 허용 허용
개수 테이블당 1개 여러 개 가능 여러 개 가능

 


CASCADE 필요성 

use shop;
show tables; 

-- member 회원가입 
-- orders 테일 1번 회원이 주문한 목록 데이터가 있다고 가정 
-- 두 테이블에 FK 관계일 때  member 테이블에 접근해서 1번 회원을 삭제할 수 있을까요? 

select * from member; 
select * from orders; 
insert into orders(member_id, total_price) values (1, 10000);

-- FK 위반 why? orders 테이블에 member id 인 1번 데이터가 존재 하기 때문에 
-- member 테이블에 1번 회원을 삭제하면 하면 orders 테이블에 member_id 1 은 무의미한 데이터가 된다. 
delete from member where id = 1;
-- 2번은 바로 삭제 가능한가?  
delete from member where id = 2; 

-- 결론 orders 테이블에 존재하는 member_id 의 값 1을 먼저 삭제하고 member 테이블에 pk 인 1번 회원을 삭제할 수 있다. 
-- orders 테이블에 데이터 삭제 
delete from orders where member_id = 1;

 


ON DELETE CASCADE - 연쇄 삭제, ON UPDATE CASCADE - (연쇄 수정)

-- [준비] 현재 orders 테이블에 걸린 정확한 FK 이름을 확인합니다.
-- 결과창의 'Create Table' 항목에서 CONSTRAINT `제약조건명` 부분을 찾으세요.
SHOW CREATE TABLE orders;

-- [단계 1] 기존의 제약 조건을 삭제합니다. 
-- (보통 자동 생성된 이름은 orders_ibfk_1 같은 형태입니다.)
ALTER TABLE orders DROP FOREIGN KEY orders_ibfk_1;

-- [단계 2] CASCADE 옵션을 추가하여 제약 조건을 새로 정의합니다.
-- 제약 조건 이름(fk_orders_member)을 직접 정해주면 나중에 관리하기 훨씬 편합니다.
ALTER TABLE orders
ADD CONSTRAINT fk_orders_member
FOREIGN KEY (member_id) REFERENCES member(id)
ON DELETE CASCADE    -- 부모 삭제 시 자식도 삭제
ON UPDATE CASCADE;   -- 부모 PK 수정 시 자식 FK도 수정

-- [단계 3] 테스트: 부모(member) 데이터 수정 시 연쇄 반응 확인
-- 1번 회원의 ID를 99로 바꿔봅니다.
UPDATE member SET id = 99 WHERE id = 1;

-- 자식(orders) 테이블을 조회하면 member_id가 자동으로 99로 바뀌어 있습니다.
SELECT * FROM orders WHERE member_id = 99;

-- [단계 4] 테스트: 부모 데이터 삭제 시 연쇄 삭제 확인
-- 99번 회원을 삭제합니다.
DELETE FROM member WHERE id = 99;

-- 자식 테이블에서 해당 주문들이 흔적도 없이 사라졌는지 확인합니다.
SELECT * FROM orders;

 


핵심 요약

PRIMARY KEY
  행을 고유하게 식별, 중복/NULL 불가, 테이블당 1개

UNIQUE KEY
  중복 값 방지, NULL 여러 개 허용, 테이블에 여러 개 가능
  실무 예: 이메일, 전화번호, 사용자명

FOREIGN KEY
  다른 테이블의 PK 참조
  없는 값 참조 → INSERT 오류
  참조 중인 행 삭제 → DELETE 오류 (CASCADE 설정 시 함께 삭제)

'MySQL' 카테고리의 다른 글

MySQL 기초 복습 - 12  (0) 2026.04.03
인덱스(Index) - 11  (0) 2026.04.03
UPDATE 와 DELETE - 9  (0) 2026.04.03
SELECT 와 WHERE - 8  (0) 2026.04.03
INSERT 구문과 제약 조건 -7  (0) 2026.04.02