조건을 위반하는 데이터를 방지해 데이터베이스의 무결성 ( Integrity )을 보장하는 규칙이다.
무결성은 데이터가 결함없이 정확하고 완전한 상태를 의미한다.
제약 조건의 종류
● 고유 제약 조건 ( Unique )
테이블에 소속된 특정 컬럼이 중복된 키를 가질 수 없는 조건
사용자 아이디, 이메일과 같은 고유한 정보를 저장할 때 사용한다.
● NULL 제약 조건 ( Null )
특정 컬럼이 아무런 값을 입력받지 않도록 설정하거나 무조건 값을 입력 받도록 설정하는 조건
데이터가 없으면 Null을 저장해 데이터가 존재하지 않다는것을 표현한다.
● 기본 키 제약 조건 ( Primary Key )
테이블 내에서 각 행 ( row )을 고유하게 식별할 수 있도록 보장하는 조건
● 외래 키 제약 조건 ( Foreign Key )
데이터베이스를 설계할 때 가장 많은 고민을 하게 될 테이블 간의 관계를 설정하는 조건
한 테이블의 컬럼 ( Column )이 다른 테이블의 특정 행 ( Row )을 참조하도록 설정하는 조건
음식 주문앱 DB 설계
고객 ( User ) 테이블
음식 ( Food ) 테이블
연관 관계 설계
고객이 음식 주문 시, 주문 정보를 어느 테이블에 넣어야 할까?
고객 테이블 또는 음식 테이블
"고객 테이블"에 주문 정보를 넣어보자
문제점 : 회원 중복
"음식 테이블"에 주문 정보를 넣어보자
그럴듯 해 보이지만.. 먹깨비 ( userID = 2 )가 '후라이드치킨'을 하나 더 시킬 경우.. 문제가 생김
문제점 : 음식 중복
'주문'을 위한 테이블이 필요 ▶ 주문 ( Order ) 테이블 추가
회원 1명은 주문 N개를 할 수 있다. ( 회원 : 주문 = 1 : N 관계 )
음식 1개는 주문 N개에 포함될 수 있다. ( 음식 : 주문 = 1 : N 관계 )
결론적으로 ( 회원 : 음식 = N : M 관계 )
ERD ( 개체 관계도 )
SQL 문
CREATE TABLE User
(
userId int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
name varchar(255) NOT NULL UNIQUE
);
CREATE TABLE Food
(
foodId int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
name varchar(255),
price int(11)
);
CREATE TABLE Order
(
orderId int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
userId int(11) NOT NULL,
foodId int(11) NOT NULL,
createdAt datetime NOT NULL DEFAULT NOW(),
FOREIGN KEY (foodId) REFERENCES Food (foodId)
ON DELETE NO ACTION
ON UPDATE CASCADE,
FOREIGN KEY (userId) REFERENCES User (userId)
ON DELETE NO ACTION
ON UPDATE CASCADE
);
기본 키 ( Primary Key ) 제약 조건
위 CREATE TABLE SQL문을 보면 PRIMARY KEY라는 조건으로 기본 키가 선언되어 있는 것을 확인 할 수 있다.
만약, 기본키를 설정하지 않은 테이블을 생성하려한다면, 특정 데이터를 찾기위한 고유한 정보가 존재하지 않기 때문에 아래와 같은 에러메세지가 출력되면서 테이블이 생성되지 않게 된다.
ERROR 1075 (42000): Incorrect table definition; there can be only one auto column and it must be defined as a key
CREATE TABLE Users
(
userId int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
name varchar(255)
);
사용자 ( User ) 테이블
userId 컬럼을 기본키로 설정한다. ( AUTO_INCREMENT 속성은 데이터가 입력될때마다 해당 속성의 값이 1씩 자동으로 증가시켜주는 속성 )
이름 ( name ) 컬럼을 가진다.
NULL 제약 조건
테이블에서 컬럼을 생성할 때 추가 조건을 작성하지 않으면 기본적으로 해당 컬럼은 NULL값을 허용하는 상태가 된다.
NULL 값을 허용하게 되면, 필수적으로 입력되어야 하는 데이터가 누락될 수 있다는 점을 기억하고 있어야한다.
NOT NULL 제약 조건을 추가해 특정 컬럼에서 NULL 값을 허용하지 않게 해줄 수 있다.
NULL 제약 조건 요구사항!
사용자 ( User ) 테이블
UserId 컬럼을 기본키로 설정한다.
이름 ( name ) 컬럼을 가진다.
이외 요구사항
사용자 테이블의 이름 컬럼은 NULL 값을 허용하지 않는다.
CREATE TABLE Users
(
userId int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
name varchar(255) NOT NULL
);
고유 제약 조건 ( Unique )
고유 제약 조건은 중복된 값을 허용하지 않도록 설정할 수 있다.
UNIQUE 제약 조건 요구사항!
사용자 ( User ) 테이블
userId 컬럼을 기본키로 설정한다.
이름 ( name ) 컬럼을 가진다.
이외 요구사항
사용자 테이블의 이름 컬럼은 NULL을 허용하지 않는다.
사용자 테이블의 이름 컬럼은 중복된 값을 허용하지 않는다.
CREATE TABLE Users
(
userId int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
name varchar(255) NOT NULL UNIQUE
);
만약, 고유 제약 조건을 할당한 컬럼에 중복된 데이터를 삽입하면 어떻게 될까?
INSERT INTO Users (name) VALUES ('정성원');
INSERT INTO Users (name) VALUES ('정성원');
Error: ER_DUP_ENTRY: Duplicate entry '정성원' for key 'Users.name'
EP_DUP_ENTRY 에러메세지가 출력되고, 데이터가 삽입되지 않은 것을 확인할 수 있다.
기본키를 적용한 컬럼은 고유 제약 조건이 자동으로 적용된다.
외래 키 제약 조건 ( Foreign Key )
외래 키 ( Foreign Key )는 테이블간의 연관 관계 ( Relation Ship )를 표현할 때 사용한다.
연관 관계는 대표적으로 3가지의 형태로 표현할 수 있다.
1:1 - 1명의 사용자 ( User ) 는 1개의 사용자 정보 ( UserInfo )를 가질 수 있다.
1:N - 1명의 사용자 ( User )는 여러개의 주문 ( Order )을 할 수 있다.
N:M - 여러명의 학생 ( Student )은 여러개의 학원 ( School )을 등록할 수 있다.
관계형 데이터베이스 ( RDB )는 각 데이터를 '테이블'이라는 표 형태의 구조에 저장한다.
여기서, 각 '테이블'은 여러 정보를 저장하며, '테이블'간에 연관 관계를 설정해, 여러 테이블에 분산된 데이터를
서로 연결하여 관리할 수 있다.
연관 관계 ( Relationship )란, 각 테이블 사이의 연결된 관계를 의미한다.
관계형 데이터베이스는 테이블 ( Table )이라는 구조를 가지며, 각 테이블은 고유한 데이터를 나타내는 행 ( row )과 데이터의 속성을 나타내는 열 ( column )을 가진다.
이 테이블들은 서로 연결될 수 있으며, 이 연결을 통해 복잡한 데이터를 관리할 수 있게 된다.
관계형 데이터베이스 ( RDB )와 비관계형 데이터베이스 ( NoSQL )의 개념
데이터 형식이 자유로운 비관계형 데이터베이스와는 달리 관계형 데이터베이스는 '테이블'이라는 개념이 존재한다.
여기서 테이블이란, 여러개의 '열( column )'과 '행( row )'을 가지는데, 이는 엑셀의 표와 유사한 형태다.
각 행 ( row )은 고유한 데이터 ( record )를 나타낸다. 각 열 ( column )은 해당 데이터의 속성 ( field )을 표현한다.
위 표를 예로 들어 설명하면
행은 test@email.com, 테스트닉네임, 1234와 같은 정보를 나타내고,
열은 이메일, 닉네임, 비밀번호와 같은 속성을 나타낸다.
주목해야할 점은 이 테이블 ( 표 )들 간에 서로 연관 관계 ( Relationship )를 가질 수 있다는 점이다.
이러한 관계를 통해 더욱 복잡한 쿼리를 작성할 수 있고, 바로 이 점이 "관계형 데이터베이스"라는 이름의 유래가 된것.
그렇다고 해서 비관계형 데이터베이스 ( NoSQL )가 좋지 않다는 것은 아니다. NoSQL은 유연한 데이터 구조를 가지기 때문에, 저장과 읽기 작업이 더욱 빠르고, 복잡한 비즈니스 로직 없이 주로 데이터 읽기와 쓰기에 중점을 둔 서버에서 주로 사용한다. ( 주로 빅데이터 환경, 단순 페이지뷰가 많은 앱 등 )
반면, 관계형 데이터베이스 ( RDB )는 더욱 복잡한 비즈니스 로직과 정형화된 데이터를 체계적으로 관리할 수 있어 더욱 안전한 서버 환경을 구성하기에 좋다. ( 보안이 중요한 기관, 은행과 같은 안전성을 중시하는 회사 등 )