본문 바로가기

DB

오라클 DB 정리 – 정규화 · 참조 무결성 · 외래키 제약 · ENUM 대체 방법

1. 데이터베이스 정규화 (Normalization)

먼저 정규화부터.
정규화는 데이터를 잘게 쪼개서 중복을 줄이고, 이상 현상을 방지하는 과정이다.

  • 1차 정규화 (1NF)
    모든 속성은 반드시 원자값(Atomic Value)이어야 한다.
    → 예를 들어, 전화번호 여러 개를 한 컬럼에 넣지 않고 별도 테이블로 분리해야 한다.
  • 2차 정규화 (2NF)
    1NF를 만족하면서, 기본키의 부분집합에만 종속된 속성을 제거한다.
    → (학생ID, 과목ID) → 성적 구조일 때, 학생 주소는 학생ID에만 종속되므로 따로 분리해야 한다.
  • 3차 정규화 (3NF)
    2NF를 만족하면서, 기본키가 아닌 속성이 다른 속성에 종속되지 않도록 분리한다.
    → 학생 테이블에 학과ID → 학과명 관계가 있으면 학과 테이블로 분리.

정리하자면, 정규화를 통해 데이터 중복을 줄이고 테이블 간 관계를 명확히 할 수 있다.


2. 참조 무결성과 외래키 제약

외래키(FK)는 반드시 다른 테이블의 기본키(PK)를 참조해야 한다.

CREATE TABLE tEmployee (
    name CHAR(10) PRIMARY KEY
);

CREATE TABLE tProject (
    projectID INT PRIMARY KEY,
    employee CHAR(10) NOT NULL,
    project VARCHAR(30) NOT NULL,
    cost INT,
    CONSTRAINT FK_emp FOREIGN KEY(employee) REFERENCES tEmployee(name)
);

이렇게 정의하면 tProject.employee 값은 반드시 tEmployee.name에 존재해야 한다. 없는 직원을 참조하려 하면 에러가 난다.
즉, 데이터 불일치를 원천 차단할 수 있다.


3. 외래키 선언 방식

실제로 FK를 선언하는 방법은 두 가지다.

  1. 컬럼 레벨에서 지정
dept_id NUMBER CONSTRAINT emp_dept_fk REFERENCES department(dept_id)
  1. 테이블 레벨에서 지정 (실무 권장)
CONSTRAINT emp_dept_fk FOREIGN KEY (dept_id) REFERENCES department(dept_id)

실무에서는 테이블 레벨 방식을 더 선호한다. 이유는 복합키 관리나 제약조건 유지보수 측면에서 훨씬 깔끔하기 때문이다.


4. 연계 참조 무결성 (Referential Actions)

외래키에는 부모 테이블 삭제/변경 시 자식 테이블이 어떻게 반응할지 정할 수 있다.

  • ON DELETE CASCADE → 부모 삭제 시 자식도 같이 삭제
  • ON DELETE SET NULL → 부모 삭제 시 자식 FK를 NULL로 변경
  • ON DELETE NO ACTION → 기본값, 부모 삭제 시 자식이 있으면 에러 발생

단, 오라클은 ON UPDATE CASCADE는 지원하지 않는다.
필요하다면 트리거를 따로 구현해야 한다는 점도 기억해 두면 좋다.


5. VARCHAR vs VARCHAR2

 

  • VARCHAR → ANSI 표준 타입이지만, 오라클 내부에서는 자동으로 VARCHAR2로 변환된다.
  • VARCHAR2 → 오라클 고유 타입, 가변 길이 문자열 저장 가능.

공식 문서에서도 VARCHAR 대신 VARCHAR2 사용을 권장한다. 앞으로는 테이블 만들 때 무조건 VARCHAR2를 써야겠다.


6. ENUM 타입 대체 (Oracle)

MySQL에서는 ENUM 타입을 쓰지만, Oracle은 ENUM을 지원하지 않는다.

대신 다음 두 가지 방법으로 대체한다.

  1. CHECK 제약조건 (간단한 경우)
status NUMBER CHECK (status IN (1,2,3,4))
  1. 코드 테이블 생성 (실무 권장)
CREATE TABLE order_status_code (
    status_code NUMBER PRIMARY KEY,
    status_name VARCHAR2(50) NOT NULL
);

CREATE TABLE tOrder (
    orderId NUMBER PRIMARY KEY,
    status NUMBER,
    CONSTRAINT fk_order_status FOREIGN KEY (status) REFERENCES order_status_code(status_code)
);

실무에서는 두 번째 방식이 더 많이 쓰인다. 상태값을 별도 테이블로 관리하면 의미 있는 값과 조인해서 조회할 수도 있고, 유지보수도 편하다.


마무리

  • 정규화로 데이터 중복을 줄이고,
  • 외래키와 제약조건으로 무결성을 보장하고,
  • 오라클 전용 특징까지 이해해야겠다