# SQL 제약조건 제약조건이란 데이터베이스 테이블에 저장되는 데이터에 대한 규칙을 정의하는 것이다. 이러한 제약 조건은 데이터의 무결성을 보장하고 데이터의 정확성을 유지하는 데 도움이 된다. SQL에서 주로 사용되는 제약 조건은 다음과 같다. - `NOT NULL` : 열에 NULL 값을 허용하지 않는다. - `DEFAULT` : 열에 기본값을 설정한다. - `UNIQUE` : 열에 중복 값을 허용하지 않는다. - `PRIMARY KEY` : 열에 고유한 값을 가지며, NULL 값을 허용하지 않는다. - `FOREIGN KEY` : 열에 다른 테이블의 기본키를 참조하는 외래키를 설정한다. - ... ## `NOT NULL` 제약조건 `NOT NULL` 제약 조건은 열에 NULL 값을 허용하지 않게 강제한다. 즉, 이 제약조건이 설정된 필드는 무조건 데이터를 가지고 있어야 한다. `NOT NULL` 제약 조건을 설정하는 방법은 다음과 같다. ```sql CREATE TABLE 테이블이름 ( 필드이름 필드타입 NOT NULL, ... ) ``` 예를 들어 다음과 같은 테이블이 있다고 가정하자. ```sql CREATE TABLE Test ( ID INT NOT NULL, Name VARCHAR(30), ReserveDate DATE, RoomNum INT ); ``` 이 때 `ID` 필드에 `NOT NULL` 제약 조건이 설정되어 있으므로 `ID` 필드에는 NULL 값을 저장할 수 없다. ```sql -- 데이터 추가 INSERT INTO Test (ID, Name, ReserveDate, RoomNum) VALUES (1, 'John Doe', '2023-01-15', 101); -- 데이터 추가 (ID 필드에 NULL 값 저장 시도) INSERT INTO Test (Name, ReserveDate, RoomNum) VALUES('John Doe', '2023-01-15', 101); /* 에러 발생 ERROR 1364 (HY000): Field 'ID' doesn't have a default value */ ``` ## `DEFAULT` 제약조건 `DEFAULT` 제약 조건은 열에 기본값을 설정한다. 즉, 이 제약조건이 설정된 필드는 데이터를 저장하지 않아도 기본값이 저장된다. `DEFAULT` 제약 조건을 설정하는 방법은 다음과 같다. ```sql CREATE TABLE 테이블이름 ( 필드이름 필드타입 DEFAULT 기본값, ... ) ``` 예를 들어 다음과 같은 테이블이 있다고 가정하자. ```sql CREATE TABLE Test ( ID INT NOT NULL DEFAULT 0, Name VARCHAR(30), ReserveDate DATE, RoomNum INT ); ``` `ID` 필드는 `NOT NULL` 제약 조건이 설정되어 있으므로 NULL 값을 허용하지 않는다. 그런데 `DEFAULT 0` 제약 조건이 설정되어 있으므로 데이터를 추가할 때 `ID` 필드에 값을 지정하지 않아도 기본값인 0이 저장된다. 따라서 다음과 같이 ID 필드에 데이터를 저장하지 않아도 데이터를 추가할 수 있다. ```sql -- 데이터 추가 INSERT INTO Test (Name, ReserveDate, RoomNum) VALUES('John Doe', '2023-01-15', 101); -- 조회 SELECT * FROM Test; /* +----+----------+-------------+---------+ | ID | Name | ReserveDate | RoomNum | +----+----------+-------------+---------+ | 0 | John Doe | 2023-01-15 | 101 | +----+----------+-------------+---------+ */ ``` ## `UNIQUE` 제약조건 `UNIQUE` 제약 조건은 열에 중복 값을 허용하지 않는다. 즉, 이 제약조건이 설정된 필드는 중복 값을 가질 수 없다. `UNIQUE` 제약 조건을 설정하는 방법은 다음과 같다. ```sql CREATE TABLE 테이블이름 ( 필드이름 필드타입 UNIQUE, ... ) ``` 예를 들어 다음과 같은 테이블이 있다고 가정하자. ```sql CREATE TABLE Test ( ID INT NOT NULL UNIQUE, Name VARCHAR(30), ReserveDate DATE, RoomNum INT ); ``` 이 테이블에서 `ID` 필드에 `UNIQUE` 제약 조건이 설정되어 있으므로 `ID` 필드에 중복 값을 저장할 수 없다. ```sql -- 데이터 추가 INSERT INTO Test (ID, Name, ReserveDate, RoomNum) VALUES (1, 'John Doe', '2023-01-15', 101); -- 데이터 추가 (ID 필드에 중복 값 저장 시도) INSERT INTO Test (ID, Name, ReserveDate, RoomNum) VALUES (1, 'Jane Smith', '2023-02-10', 102); /* 에러 발생 ERROR 1062 (23000): Duplicate entry '1' for key 'ID' */ ``` ## `PRIMARY KEY` 제약조건 `PRIMARY KEY` 는 `기본 키`라고도 한다. `PRIMARY KEY` 제약 조건은 열에 고유한 값을 가지며, NULL 값을 허용하지 않는다. 즉, `PRIMARY KEY` 는 `UNIQUE`와 `NOT NULL` 제약 조건을 모두 가지고 있다. `UNIQUE`와 `NOT NULL` 두 제약조건과 차이점이 있다면, `PRIMARY KEY`는 테이블에서 한 개의 열만 가질 수 있다. `PRIMARY KEY`를 설정하는 방법은 다음과 같다. ```sql CREATE TABLE 테이블이름 ( 필드이름 필드타입 PRIMARY KEY, ... ) ``` 예를 들어 다음과 같은 `customers` 테이블이 있다고 가정하자. ```sql CREATE TABLE customers ( customer_id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(100) NOT NULL, email VARCHAR(100) NOT NULL, country VARCHAR(50) NOT NULL ); ``` 이 테이블에서 `customer_id` 열은 기본키이다. 이 열은 각 행을 고유하게 식별한다. 위에서 사용한 `AUTO_INCREMENT`는 자동으로 증가하는 숫자를 의미한다. 따라서 `customer_id` 열에 값을 지정하지 않으면 자동으로 증가하는 숫자가 저장된다. 따라서 다음과 같이 값을 저장해도 `customer_id` 열에는 자동으로 증가하는 숫자가 저장된다. ```sql -- 데이터 추가 INSERT INTO customers (name, email, country) VALUES ('John Doe', 'john.doe@example.com', 'USA'); -- 조회 SELECT * FROM customers; /* +-------------+----------+----------------------+---------+ | customer_id | name | email | country | +-------------+----------+----------------------+---------+ | 1 | John Doe | john.doe@example.com | USA | +-------------+----------+----------------------+---------+ */ ``` 물론, `AUTO_INCREMENT`가 지정되어 있어도 `customer_id` 열에 값을 지정할 수 있다. ```sql -- 데이터 추가 INSERT INTO customers (customer_id, name, email, country) VALUES (100, 'John Doe', 'john.doe@example.com', 'USA'); -- 조회 SELECT * FROM customers; /* +-------------+----------+----------------------+---------+ | customer_id | name | email | country | +-------------+----------+----------------------+---------+ | 1 | John Doe | john.doe@example.com | USA | | 100 | John Doe | john.doe@example.com | USA | +-------------+----------+----------------------+---------+ */ ``` 그러나 `customer_id` 열에 중복 값을 저장하려고 하면 오류가 발생한다. ```sql -- PRIMARY KEY가 중복된 데이터 추가 시도 INSERT INTO customers (customer_id, name, email, country) VALUES (100, 'John Doe', 'john.doe@example.com', 'USA'); /* 에러 발생 ERROR 1062 (23000): Duplicate entry '100' for key 'PRIMARY' */ ``` ### 기본 키 설정 시 주의사항 기본키는 테이블의 각 행을 고유하게 식별해야 한다. 따라서 `이름`과 같이 중복될 가능성이 있는 열을 기본키로 설정하면 안된다. 또한 뒤에서 다룰 외래키에 관련된 문제로, 기본키를 변경하거나 삭제하는 것은 권장되지 않기 때문에 변경할 가능성이 없는 열을 기본키로 설정하는 것이 좋다. ## `FOREIGN KEY` 제약조건 `FOREIGN KEY`는 `외래 키`라고도 한다. 외래 키는 다른 테이블의 기본키를 참조하는 열이며, 각 테이블간에 관계를 설정하려면 외래키(foreign key)를 사용한다. 즉, 외래키는 **일종의 링크**이다. `FOREIGN KEY`를 설정하는 방법은 다음과 같다. ```sql CREATE TABLE 테이블이름 ( 필드이름 필드타입, ..., [CONSTRAINT 제약조건이름] FOREIGN KEY (필드이름) REFERENCES 테이블이름 (필드이름) ) ``` 이 때 `REFERENCES` 키워드 뒤에는 참조할 테이블의 이름과 참조할 열의 이름을 지정한다. 예를 들어 위에서 사용한 `customers` 테이블이 있다고 가정하자. 이 테이블은 `customer_id` 열을 기본키로 가지고 있다. `customers` 테이블과 관련된 `orders` 테이블을 생성하려면 다음과 같이 `FOREIGN KEY`를 사용한다. ```sql CREATE TABLE orders ( order_id INT AUTO_INCREMENT PRIMARY KEY, customer_id INT, order_date DATE NOT NULL, amount DECIMAL(10, 2) NOT NULL, FOREIGN KEY (customer_id) REFERENCES customers(customer_id) ); ``` `orders` 테이블에서 `customer_id` 열은 외래키이다. 이 열은 `customers` 테이블의 `customer_id` 열을 참조한다. 따라서 `orders` 테이블에 데이터를 추가할 때 `customer_id` 열에 `customers` 테이블에 있는 `customer_id` 열의 값을 지정해야 한다. ```sql -- 데이터 추가 INSERT INTO orders (customer_id, order_date, amount) VALUES (1, '2023-01-15', 150.00); -- 조회 SELECT * FROM orders; /* +----------+-------------+------------+--------+ | order_id | customer_id | order_date | amount | +----------+-------------+------------+--------+ | 1 | 1 | 2023-01-15 | 150.00 | +----------+-------------+------------+--------+ */ ``` `customer_id` 열에 `customers` 테이블에 없는 값을 저장하려고 하면 오류가 발생한다. ```sql -- FOREIGN KEY가 없는 데이터 추가 시도 INSERT INTO orders (customer_id, order_date, amount) VALUES (-1, '2023-01-15', 150.00); /* 에러 발생 ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint fails (`mydb`.`orders`, CONSTRAINT `orders_ibfk_1` FOREIGN KEY (`customer_id`) REFERENCES `customers` (`customer_id`)) */ ``` 이렇듯 `orders` 테이블에는 `customers` 테이블에 없는 `customer_id` 값을 저장할 수 없게 된다.