> For the complete documentation index, see [llms.txt](https://docs.sysout.co.kr/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.sysout.co.kr/database/oracle/structure-query-language/user-query/manage-table/table-column-constraint.md).

# 테이블 항목 제약 조건

## 테이블 항목 제약 조건

이 문서에서는 테이블에 설정할 수 있는 `제약조건`에 대해서 살펴본다.

### 제약 조건

DBMS에서 테이블은 데이터를 저장하기 위한 목적으로 생성한다. 생성할 때에는 기대하는 데이터의 형태가 있기 마련이다. 제약 조건(Constraint)이란, **기대하는 데이터만 추가가 가능**하도록 강제하기 위한 키워드를 말한다.

### 제약 조건 종류

오라클에서 테이블에 설정할 수 있는 제약 조건의 종류는 다음과 같다.

* PRIMARY KEY(기본키)
* NOT NULL(필수값)
* UNIQUE(중복불가)
* CHECK(특정값)
* DEFAULT(기본값)
* FOREIGN KEY(외래키)

### 제약 조건이 없는 테이블 예시

다음 테이블을 예로 들어본다.

> table student

| code | name | score | regist     |
| ---- | ---- | ----- | ---------- |
| 1    | 피카츄  | 100   | 2020-05-01 |
| 2    | 파이리  | 50    | 2020-05-03 |
| 3    | 라이츄  | 99    | 2020-05-05 |
| 4    | 꼬부기  | 70    | 2020-05-05 |

* `code` : **고유번호**가 저장되는 컬럼으로, **식별을 위한 숫자 값**이 들어올 것이라 예상
* `name` : **이름**이 저장되는 컬럼으로, **문자열 데이터**가 들어올 것이라 예상
* `score` : **점수**가 저장되는 컬럼으로, **0에서 100 사이의 정수**가 저장될 것이라 예상
* `regist` : **등록일**이 저장되는 컬럼으로, 날짜 형태의 **현재 시간 정보**가 저장될 것이라 예상

```sql
CREATE TABLE student(
code NUMBER,
name VARCHAR2(21),
score number,
regist date
);
```

### 제약 조건이 없는 테이블에 데이터 추가

### **NULL 데이터 추가**

제약 조건이 없는 테이블에 데이터를 추가하여 발생할 수 있는 문제점을 알아본다.

```sql
INSERT INTO student VALUES(null, null, null, null);
```

위 구문을 실행하면 모든 컬럼이 `null`인 이상한 데이터가 student 테이블에 들어가는 것을 확인할 수 있다. 이러한 데이터는 기대한 값이 아니지만, 방어 수단이 없기 때문에 속수무책으로 추가되는 것을 구경할 수 밖에 없다.&#x20;

`null`이 들어가면 안되는 컬럼은 **code, name, regist** 이다. 필요하다면 score도 null이 설정될 수 없도록 처리할 수 있다. 이는 `NOT NULL` 제약 조건을 통하여 해결할 수 있다.

```sql
CREATE TABLE student(
code NUMBER NOT NULL,
name VARCHAR2(21) NOT NULL,
score number,
regist date NOT NULL
);
```

### 중복 데이터 추가

```sql
INSERT INTO student VALUES(5, '뮤츠', 35, sysdate);
```

위의 데이터는 이상 없이 추가된다. 하지만, 동일한 데이터를 두 번 이상 추가할 경우는 문제가 생다.

| code | name | score | regist     |
| ---- | ---- | ----- | ---------- |
| 5    | 뮤츠   | 35    | 2020-05-26 |
| 5    | 뮤츠   | 35    | 2020-05-26 |
| 5    | 뮤츠   | 35    | 2020-05-26 |
| 5    | 뮤츠   | 35    | 2020-05-26 |
| 5    | 뮤츠   | 35    | 2020-05-26 |

이와 같이 들어갔다고 생각해보면, 중복 데이터가 문제가 되는 이유를 알 수 있다. 실제로 데이터는 5개이지만, 구분할 방법이 없기 때문에 1개가 들어있는 것과 마찬가지로 사용할 수 밖에 없게 됩니다. 중복이 발생하면 안되는 컬럼은 **code** 이다.

이는 `UNIQUE` 제약조건을 통하여 해결할 수 있다. 중복 데이터가 불가한 컬럼에 `UNIQUE` 를 조건으로 설정하면 중복 데이터 추가시 **무결성 제약조건 위반** 오류가 발생한다.

{% hint style="info" %}
UNIQUE 조건은 반드시 NOT NULL 조건보다 뒤에 위치해야 한다
{% endhint %}

```sql
CREATE TABLE student(
code NUMBER NOT NULL UNIQUE,
name VARCHAR2(21) NOT NULL,
score number,
regist date NOT NULL
);
```

### **범위를 벗어난 데이터 추가**

위의 두 경우에 해당하지 않지만 문제가 되는 상황도 있다.

```sql
INSERT INTO student VALUES(6, '야도란', 1000, sysdate);
```

위의 구문은 정상적으로 추가가 된다. 하지만 우리가 기대한 점수값은 **0 이상 100 이하의 정수**이므로 정상적인 데이터가 추가되었다고 보기 어렵다. 이처럼 값에 대한 원하는 기준이 있는 경우에 특정하여 사용할 수 있으며, 이에 해당하는 컬럼은 **score** 이다.(code도 가능하다)

특정값을 설정할 경우 `CHECK` 제약조건을 사용할 수 있다. `CHECK` 뒤에는 원하는 값의 조건을 설정할 수 있다.

{% hint style="info" %}
CHECK 조건은 반드시 NOT NULL 조보다 뒤에 위치해야 한다
{% endhint %}

```sql
CREATE TABLE student(
code NUMBER NOT NULL UNIQUE,
name VARCHAR2(21) NOT NULL,
score number CHECK(score between 0 and 100),
regist date NOT NULL
);
```

### **기본 값이 필요한 경우**

위의 테이블에서 `등록일`의 경우에는 데이터가 추가될 당시의 시각이 자동으로 저장되어야 한다. 하지만 우리가 `sysdate`라고 적어주지 않으면 시간이 추가가 되지 않기 때문에 불편하다. 이러한 경우 **기본값**을 설정하여 사용할 수 있다. 기본값은 `DEFAULT` 를 컬럼 형태 뒤에 추가하여 적용할 수 있으며, 반드시 NOT NULL보다 먼저 작성되어야 합니다.

{% hint style="info" %}
DEFAULT 조건은 NOT NULL 조건보다 앞에 위치해야 한
{% endhint %}

```sql
CREATE TABLE student(
code NUMBER NOT NULL UNIQUE,
name VARCHAR2(21) NOT NULL,
score number CHECK(score between 0 and 100),
regist date DEFAULT sysdate NOT NULL
);
```

### 기본 키 제약 조건

기본 키(PRIMARY KEY)란 `테이블을 대표할 수 있는 항목`을 말한다. 기본 키가 되기 위해서는 다음의 조건이 필수다.

* 모든 항목이 기본 키로 식별이 가능할 것(UNIQUE)
* 반드시 값이 설정될 것(NULL 불가)

기본 키에는 `INDEX` 가 자동으로 설정되어 검색 성능이 향상된다. 따라서 `student` 테이블의 경우 NOT NULL이면서 UNIQUE 조건을 가진 `code` 항목에 기본 키 설정을 하면 `code`를 통한 검색 성능이 향상된다.

```sql
CREATE TABLE student(
code NUMBER PRIMARY KEY,
name VARCHAR2(21) NOT NULL,
score number CHECK(score between 0 and 100),
regist date DEFAULT sysdate NOT NULL
);
```

기본 키는 여러 개의 컬럼을 합쳐서 사용할 수도 있다. 이러한 형태를 복합 키(Composite key)라고 한다. 예를 들어, 날짜와 순서를 합쳐서 고유 번호로 사용하고 싶은 경우 다음과 같이 테이블을 구현할 수 있다.\
다음 예시는 `주문(Order)` 테이블다.

```sql
CREATE TABLE order(
order_date DATE NOT NULL,
order_sequence NUMBER NOT NULL,
order_product_name VARCHAR2(60) NOT NULL,
order_count NUMBER DEFAULT 0 NOT NULL,
PRIMARY KEY(order_date, order_sequence)
);
```

위와 같은 경우 `order_date`와 `order_sequence`는 각각 중복이 가능하지만, 두 개가 모두 같은 데이터는 존재할 수 없는 복합 키로 설정되었다. 복합 키는 컬럼 우측에 작성할 수 없기 때문에 테이블 작성 후에 설정한다.

### 외래키 제약조건

외래 키(Foreign key)란 다른 테이블을 참조하기 위한 제약 조건이다. 주로 테이블을 분할해야 하는 경우에 사용하며, 외래 키가 필요한 다양한 상황들이 존재한다. 이는 해당 문서에서 상세히 다룬다.

{% content-ref url="/pages/-MfWSxBwnlPUoewGY693" %}
[외래키 제약조건](/database/oracle/structure-query-language/user-query/manage-table/foreign-key-constraint.md)
{% endcontent-ref %}
