우와한 개발자

[SQL] Oracle 제약조건(Constraint) 정리 - NOT NULL / UNIQUE / PK / FK / CHECK, 제약조건 활성화/비활성화

by 우와한개발자

[제약조건 Constraint ]

  • 테이블의 해당 열에 사용자가 원치 않은 데이터가 입력, 수정, 삭제되는 것을 방지하기 위한 조건
  • 제약조건은 추가/삭제는 가능하나 수정 불가
  • 제약조건 활성화또는 비활성화 가능

1. 제약조건 종류

제약조건 의미 NULL 허용 중복 허용 테이블당 개수 복합키
NOT NULL NULL 값 입력 불가 제한 없음
UNIQUE 중복 값 불가 제한 없음
PRIMARY KEY NOT NULL과 UNIQUE 합친 것 1개
FOREIGN KEY 다른 테이블의 PK 또는 UNIQUE 컬럼 참조 제한 없음
CHECK 특정 조건을 만족하는 값만 허용 제한 없음

1) NOT NULL

  • NULL 값 입력 불가
  • 열 레벨만 가능(단, MODIFY절 사용해 NOT NULL 추가 가능)
ename VARCHAR2(20) NOT NULL

-- 기존 컬럼에 NOT NULL 추가
ALTER TABLE emp MODIFY ename NOT NULL;
⚠️MODIFY로 NOT NULL을 추가할 때 기존 데이터 중 NULL이 하나라도 있으면 오류 발생.
- 반드시 NULL 데이터를 먼저 정리하고 제약조건을 걸어야 함.

 

2) UNIQUE

  • 중복 값 불가
  • NULL은 허용 (NULL은 값이 없어 비교 자체가 불가능하여 여러 개 가능)
-- 열 레벨
email VARCHAR2(100) UNIQUE

-- 테이블 레벨
CONSTRAINT emp_uk UNIQUE (email)

 

3) PRIMARY KEY

  • NOT NULL과 UNIQUE 합친 것
  • 테이블당 1개만 가능, 복합키 가능
-- 열 레벨
empno NUMBER(4) PRIMARY KEY

-- 테이블 레벨 (복합키)
CONSTRAINT emp_pk PRIMARY KEY (empno, deptno)

 

4) FOREIGN KEY

  • 다른 테이블의 PK 또는 UNIQUE 컬럼 참조
  • 참조 무결성 보장
-- 열 레벨
deptno NUMBER REFERENCES dept(deptno)

-- 테이블 레벨
CONSTRAINT emp_fk FOREIGN KEY (deptno) REFERENCES dept(deptno)
⚠️ 부모 테이블의 행을 삭제할 때 자식 테이블에 참조 중인 행이 있으면 오류 발생.
- ON DELETE CASCADE나 ON DELETE SET NULL 옵션으로 처리 가능
CONSTRAINT emp_fk FOREIGN KEY (deptno) REFERENCES dept(deptno)
    ON DELETE CASCADE    -- 부모 삭제 시 자식도 같이 삭제
    ON DELETE SET NULL   -- 부모 삭제 시 자식 컬럼을 NULL로

 

5) CHECK

  • 특정 조건을 만족하는 값만 허용
-- 열 레벨
salary NUMBER CHECK (salary > 0)

-- 테이블 레벨
CONSTRAINT emp_ck CHECK (salary BETWEEN 1000 AND 99999)
⚠️ CHECK 조건에서 NULL은 통과됨. NULL을 막으려면 NOT NULL을 따로 걸어야 함

 

  • CHECK 조건에 사용할 수 없는 것
구분 예시 이유
Pseudo 컬럼 CURRVAL, NEXTVAL, LEVEL, ROWNUM 행마다 고정된 값이 아님
날짜/환경 함수 SYSDATE, UID, USER, USERENV 실행 시점마다 값이 바뀜
다른 행 참조 서브쿼리 CHECK는 현재 행만 검사 가능

 

6) DEFAULT (엄밀히는 제약조건 아니지만 같이 씀)

  • 값을 입력하지 않았을 때 자동으로 들어갈 기본값
hire_date DATE DEFAULT SYSDATE

 

2. 제약조건 정의

구분 열 레벨 테이블 레벨
위치 컬럼 옆 컬럼 선언 끝난 후
제약조건 이름 지정 가능하지만 생략 많이 함 ⭕ CONSTRAINT로 명시
복합키 ❌ 불가 ⭕ 가능
NOT NULL ⭕ 열 레벨만 가능 ❌ 불가

 

1) 열 레벨 (Column Level)에서 정의

  • 컬럼 정의할 때 바로 옆에 붙이는 방식
-- 이름 지정 안하는 경우 : 자동으로 SYS_C007382 같은 이름 붙여버림
CREATE TABLE emp (
    empno   NUMBER(4)    PRIMARY KEY,        -- 열 레벨
    ename   VARCHAR2(20) NOT NULL,           -- 열 레벨
    salary  NUMBER       CHECK (salary > 0), -- 열 레벨
    deptno  NUMBER(2)    REFERENCES dept(deptno) -- 열 레벨
);

-- 이름 지정하는 경우 : CONSTRAINT 제약조건명
CREATE TABLE emp (
    empno  NUMBER(4)    CONSTRAINT emp_empno_pk PRIMARY KEY,
    ename  VARCHAR2(20) CONSTRAINT emp_ename_nn NOT NULL,
    salary NUMBER       CONSTRAINT emp_salary_ck CHECK (salary > 0)
);

 

2) 테이블 레벨 (Table Level)에서 정의

  • 컬럼 정의를 다 끝낸 후 아래에 따로 선언하는 방식
CREATE TABLE emp (
    empno   NUMBER(4),
    ename   VARCHAR2(20) NOT NULL,
    salary  NUMBER,
    deptno  NUMBER(2),

    CONSTRAINT emp_pk PRIMARY KEY (empno),            -- 테이블 레벨
    CONSTRAINT emp_ck CHECK (salary > 0),             -- 테이블 레벨
    CONSTRAINT emp_fk FOREIGN KEY (deptno)            -- 테이블 레벨
        REFERENCES dept(deptno)
);
⚠️ 복합 기본키처럼 여러 컬럼을 묶어서 제약조건을 걸어야 할 때는 반드시 테이블 레벨로 써야 함
-- 복합키 예시 (열 레벨로는 불가)
CREATE TABLE order_item (
    order_id   NUMBER,
    product_id NUMBER,
    quantity   NUMBER,

    CONSTRAINT order_item_pk PRIMARY KEY (order_id, product_id) -- 테이블 레벨만 가능
);

 

3. 제약조건 조회 : Oracle 전용 

  • 딕셔너리 뷰를 통해 현재 테이블에 걸린 제약조건 확인 가능
-- 제약조건 목록 조회
SELECT constraint_name, constraint_type, status
FROM user_constraints
WHERE table_name = 'EMP';

-- 제약조건이 걸린 컬럼까지 조회
SELECT c.constraint_name, c.constraint_type, cc.column_name
FROM user_constraints c
JOIN user_cons_columns cc ON c.constraint_name = cc.constraint_name
WHERE c.table_name = 'EMP';
constraint_type 값 의미
P PRIMARY KEY
U UNIQUE
R FOREIGN KEY (Referential)
C CHECK / NOT NULL
⚠️ NOT NULL과 CHECK 둘 다 C로 표시됨. 구분하려면 search_condition 컬럼 확인

 

4. 제약조건 추가/삭제

  • 제약조건은 추가/삭제는 가능하나 수정은 불가
  • 수정이 필요하면 삭제 후 다시 추가해야 함
-- 추가
ALTER TABLE emp ADD CONSTRAINT emp_pk PRIMARY KEY (empno);

-- 삭제
ALTER TABLE emp DROP CONSTRAINT emp_pk;

-- PK는 이름 없이도 삭제 가능
ALTER TABLE emp DROP PRIMARY KEY;

 

5. 제약조건 활성화/비활성화 : Oracle 전용 

  • 제약조건을 삭제하지 않고 일시적으로 끄거나 켤 수 있음
  • 대량 데이터 INSERT 시 성능 향상 목적으로 주로 사용
옵션 기존 데이터 변경 신규 데이터 삽입 기존 데이터 조회
ENABLE VALIDATE
ENABLE NOVALIDATE
DISABLE NOVALIDATE
DISABLE VALIDATE

1) 비활성화

ALTER TABLE 테이블명
    DISABLE [NOVALIDATE | VALIDATE] 
   CONSTRAINT 제약조건명
구분 설명
DISABLE NOVALIDATE 해당 열의 제약조건만 비활성화(기본값
DISABLE VALIDATE 해당 테이블 읽기만 가능(테이블에 대한 INSERT/UPDATE/DELETE 모두 불가)
-- 기본 비활성화
ALTER TABLE emp DISABLE CONSTRAINT emp_pk;

-- CASCADE : 참조 중인 자식 FK도 함께 비활성화
ALTER TABLE dept DISABLE CONSTRAINT dept_pk CASCADE;

 

2) 활성화

ALTER TABLE 테이블명
    ENABLE [NOVALIDATE | VALIDATE]
    CONSTRAINT 제약조건명;
구분 기존 데이터 검증 이후 데이터 검증
ENABLE VALIDATE (기본값)
ENABLE NOVALIDATE
-- 기본 활성화 (기존 데이터도 전부 검증)
ALTER TABLE emp ENABLE CONSTRAINT emp_pk;

-- 기존 데이터는 무시, 이후 데이터만 검증
ALTER TABLE emp ENABLE NOVALIDATE CONSTRAINT emp_pk;
⚠️ ENABLE 시 기존 데이터가 제약조건을 위반하면 오류 발생.
- 활성화 전에 데이터 정합성 확인 필요

블로그의 정보

우와한개발자 님의 블로그

우와한개발자

활동하기