Oracle DDL 기초 정리 - SEQUENCE, 제약조건, ALTER TABLE

scminy0527·2026년 3월 10일

DBeaver 환경에서 Oracle DBMS를 실습하며 정리한 DDL 기초 개념 노트입니다.


1. SEQUENCE — 자동 증가 번호 생성기

SEQUENCE란?

테이블의 특정 컬럼에 자동으로 순차적인 번호를 부여하고 싶을 때 사용하는 독립적인 객체다.

MySQL의 AUTO_INCREMENT와 유사한 역할이지만, Oracle은 테이블에 내장된 개념이 아니라 별도의 객체로 분리되어 있다는 차이가 있다.

생성 방법

CREATE SEQUENCE SEQ_CAR;

핵심 포인트 — TABLE과의 연결

SEQUENCE와 TABLE은 DDL 단계에서 직접 연결되지 않는다.

CREATE SEQUENCE SEQ_CAR;

CREATE TABLE TBL_CAR(
    ID         NUMBER        CONSTRAINT PK_CAR PRIMARY KEY,
    CAR_NAME   VARCHAR2(255) NOT NULL,
    CAR_BRAND  VARCHAR2(255) NOT NULL,
    CAR_PRICE  NUMBER        NOT NULL,
    CAR_COLOR  VARCHAR2(255) NOT NULL,
    CAR_CREATE_AT TIMESTAMP  DEFAULT CURRENT_TIMESTAMP,
    CAR_SEATER NUMBER        NOT NULL
);

위 코드만 봐서는 SEQUENCE와 TABLE 사이의 연결고리가 없어 보이는게 정상이다.
실제 연결은 INSERT 시점에 .NEXTVAL을 호출하는 방식으로 이루어진다. (INSERT는 추후 정리 예정)

SEQUENCE 주요 키워드

키워드설명
SEQ_CAR.NEXTVAL다음 값 반환 (호출할 때마다 1씩 증가)
SEQ_CAR.CURRVAL현재 값 반환 (증가하지 않음)

Oracle 12c 이상 — DEFAULT로 연결하는 방법

CREATE TABLE TBL_CAR(
    ID NUMBER DEFAULT SEQ_CAR.NEXTVAL CONSTRAINT PK_CAR PRIMARY KEY,
    -- ...
);

이렇게 하면 INSERT 시 ID 컬럼을 생략해도 자동으로 SEQUENCE 값이 들어간다.


2. 제약조건 (Constraints)

PRIMARY KEY

ID NUMBER CONSTRAINT PK_CAR PRIMARY KEY

PRIMARY KEY 하나에 아래 두 가지 제약이 자동으로 포함된다.

  • UNIQUE — 중복값 불가
  • NOT NULL — NULL 불가

즉, PRIMARY KEY 컬럼에 별도로 UNIQUE나 NOT NULL을 추가로 선언할 필요가 없다.

UNIQUE vs NOT NULL — 일반 컬럼에서

EMAIL처럼 중요한 컬럼이지만 PRIMARY KEY가 아닌 경우, 두 제약조건을 모두 명시해야 완전한 무결성을 확보할 수 있다.

EMAIL VARCHAR2(255) NOT NULL UNIQUE

각각 빠졌을 때의 문제점은 아래와 같다.

-- UNIQUE만 있을 때 → NULL 값을 여러 행에 허용 (이메일 없는 회원 여럿 가능)
EMAIL VARCHAR2(255) UNIQUE

-- NOT NULL만 있을 때 → 같은 이메일로 여러 계정 생성 가능 (중복 허용)
EMAIL VARCHAR2(255) NOT NULL

-- 둘 다 있을 때 ✅ → 반드시 입력해야 하고, 중복도 불가
EMAIL VARCHAR2(255) NOT NULL UNIQUE

Oracle에서 UNIQUE 제약조건은 NULL을 중복으로 보지 않기 때문에,
NULL은 여러 행에 들어갈 수 있다는 점을 주의하자.

PRIMARY KEY vs UNIQUE 비교 정리

제약조건UNIQUENOT NULL
UNIQUE❌ (NULL 허용)
PRIMARY KEY✅ (NULL 불가)

3. DATE vs TIMESTAMP

Oracle에서 두 자료형의 차이는 자주 헷갈리는 부분이다.

주의: MySQL 등 다른 DB와 달리 Oracle의 DATE는 시/분/초까지 저장한다.

DATETIMESTAMP
년 / 월 / 일
시 / 분 / 초
밀리초 / 마이크로초
시간대 (TimeZone)✅ (옵션)
-- DATE : 초까지
2024-01-15 14:30:25

-- TIMESTAMP : 나노초까지
2024-01-15 14:30:25.123456789

-- TIMESTAMP WITH TIME ZONE : 시간대까지
2024-01-15 14:30:25.123456789 +09:00

언제 무엇을 쓸까?

-- 일반적인 날짜/시간 기록은 DATE로 충분
JOIN_DATE DATE        -- 가입일, 생년월일 등

-- 정밀한 시간이 필요할 때 TIMESTAMP
CAR_CREATE_AT TIMESTAMP  -- 로그, 트랜잭션 기록 등

4. ALTER TABLE — 테이블 구조 변경

테이블을 생성한 이후에도 구조를 변경할 수 있다.

자주 쓰는 ALTER TABLE 문법

-- 컬럼 추가
ALTER TABLE TBL_CAR ADD CAR_FUEL VARCHAR2(50);

-- 컬럼 삭제 (COLUMN 키워드 필수!)
ALTER TABLE TBL_CAR DROP COLUMN CAR_COLOR;

-- 자료형 / 크기 변경
ALTER TABLE TBL_CAR MODIFY CAR_NAME VARCHAR2(500);

-- 컬럼 이름 변경
ALTER TABLE TBL_CAR RENAME COLUMN CAR_COLOR TO CAR_COLOUR;

-- NOT NULL 추가
ALTER TABLE TBL_USER MODIFY USER_NAME NOT NULL;

-- NOT NULL 해제
ALTER TABLE TBL_USER MODIFY USER_NAME NULL;

-- DEFAULT 값 설정
ALTER TABLE TBL_USER MODIFY USER_NAME DEFAULT 'SAM';

-- DEFAULT 값 제거
ALTER TABLE TBL_USER MODIFY USER_NAME DEFAULT NULL;

DROP COLUMN에서 COLUMN 키워드를 빠뜨리면 오류가 발생하니 주의하자.
ALTER TABLE TBL_CAR DROP CAR_COLOR; ← 이렇게 하면 오류!

제약조건 추가 / 제거

-- UNIQUE 추가
ALTER TABLE TBL_USER ADD CONSTRAINT UQ_USER_EMAIL UNIQUE (USER_EMAIL);

-- UNIQUE 제거
ALTER TABLE TBL_USER DROP CONSTRAINT UQ_USER_EMAIL;

제약조건 확인하는 법

ALTER로 제약조건을 추가했을 때 실제로 적용됐는지 확인하는 방법은 아래와 같다.

-- 제약조건 타입 확인
SELECT CONSTRAINT_NAME, CONSTRAINT_TYPE, STATUS
FROM USER_CONSTRAINTS
WHERE TABLE_NAME = 'TBL_CAR';
CONSTRAINT_TYPE의미
PPRIMARY KEY
UUNIQUE
CCHECK / NOT NULL
RFOREIGN KEY
-- 어떤 컬럼에 걸려있는지 함께 확인
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 = 'TBL_CAR';

UNIQUE는 CREATE 단계에서 설정하는게 좋은 이유

ALTER로 UNIQUE를 나중에 추가하는 문법 자체는 간단하지만, 이미 중복 데이터가 들어가 있으면 제약조건 추가 자체가 실패한다.

-- 중복 데이터가 있을 경우 아래 오류 발생
-- ORA-02299: 중복 키가 있어서 제약조건 추가 불가
CREATE 단계ALTER 나중에
문법 복잡도간단간단
데이터 없을 때
데이터 이미 있을 때❌ 중복 있으면 오류

따라서 설계 단계에서 확실히 정해두는 습관이 중요하다.


5. 외래키 (FOREIGN KEY) — 테이블 간 관계

두 테이블이 관계를 맺을 때 기본키(PK)와 외래키(FK)를 사용한다.

핵심 규칙 — 생성 순서

FK가 참조하는 PK 테이블이 반드시 먼저 존재해야 한다.

-- ✅ 올바른 생성 순서
CREATE TABLE TBL_MEMBER (          -- 1️⃣ PK 테이블 먼저
    ID    NUMBER PRIMARY KEY,
    EMAIL VARCHAR2(255) NOT NULL UNIQUE
);

CREATE TABLE TBL_ORDER (           -- 2️⃣ FK 테이블 나중에
    ID        NUMBER PRIMARY KEY,
    MEMBER_ID NUMBER REFERENCES TBL_MEMBER(ID)
);

삭제할 때는 반대 순서

DROP TABLE TBL_ORDER;    -- 1️⃣ FK 테이블 먼저 삭제
DROP TABLE TBL_MEMBER;   -- 2️⃣ PK 테이블 나중에 삭제

생성은 PK → FK 순서, 삭제는 FK → PK 순서
"참조 당하는 쪽이 먼저 존재해야 한다"고 기억하면 쉽다.


마무리

이번 학습에서 다룬 내용을 한 줄씩 정리하면 아래와 같다.

  • SEQUENCE — 독립 객체이며 INSERT 시점에 .NEXTVAL로 연결
  • PRIMARY KEY — UNIQUE + NOT NULL이 자동 포함
  • 중요 컬럼 — UNIQUE + NOT NULL을 직접 명시해야 완전한 무결성 확보
  • DATE — Oracle에서는 시/분/초까지 저장 (밀리초 이상은 TIMESTAMP)
  • ALTER TABLE — 컬럼 삭제 시 DROP COLUMN 키워드 필수
  • FK 테이블 생성 — 참조 대상 PK 테이블이 반드시 먼저 존재해야 함

다음 포스팅에서는 INSERT, UPDATE, DELETE 등 DML 구문을 정리할 예정이다.

profile
비전공자에서 시작해 Flutter로 실서비스를 만들었고, 더 깊은 개발을 향해 계속 성장 중인 개발자

0개의 댓글