- 컬럼마다 들어가야 할 데이터 타입 지정
- 제약조건(constraint) 부여 (unique, not null, default 등)
- 체크 제약조건(check constraint) 부여 -> 특정 조건에만 허용하도록 별도 로직 추가
- 데이터 타입은 DB 종류마다 다르나 not null, unique, check, default 등은 공통
예) 영화 정보를 저장하는 테이블 생성 (Sqlite)
CREATE TABLE movies(
movie_id INTEGER PRIMARY KEY AUTOINCREMENT, -- 영화id를 대체 기본키로 사용. 정수 타입. 항상 새롭고 고유한 id값을 기본키로 받음(AUTOINCREMENT)
title TEXT UNIQUE NOT NULL, -- 제목은 텍스트 타입, 유니크해야 하고 not null
released INTEGER NOT NULL CHECK (released > 0), -- 개봉일은 양의 정수 타입만, not null
overview TEXT NOT NULL CHECK (LENGTH(overview) <= 100), -- 개요는 텍스트 타입 100자 이하, not null
rating REAL NOT NULL CHECK (rating BETWEEN 0 AND 10), -- 평점은 실수 타입이면서 0에서 10사이만, not null
director TEXT, -- 감독은 텍스트 타입
for_kids INTEGER NOT NULL DEFAULT 0 CHECK (for_kids BETWEEN 0 AND 1), -- 유아용 여부는 정수 타입이며 0 또는 1만 허용 기본값은 0, not null
-- poster BLOB -- 이미지(권장 x) => 이미지 경로를 텍스트를 저장하는 걸 권장
) STRICT; -- STRICT: INSERT 할 때마다 엄격하게 데이터 타입을 검사
예) 사용자 정보를 저장하는 테이블 생성 (MySQL)
CREATE TABLE users (
user_id BIGINT UNSIGNED PRIMARY KEY AUTO_INCREMENT, -- 큰 공간을 저장할 수 있는 정수형. pk 경우 공간이 부족하면 안 되기 때문. unsigned는 0 이상 양수만
username CHAR(10) NOT NULL, -- 'sunbok' -> 'sunbok ' 10자 보다 적으면 공백 패딩. 10자 넘어가면 에러, 최대 255
email VARCHAR(50) NOT NULL, -- VARCHAR: 가변적인 string 길이를 가진 데이터
gender ENUM('Male', 'Female') NOT NULL, -- ENUM: column을 'Male', 'Female'만 지정하게 제한
interests
SET ( -- SET: 한 행에 여러 값 선택 가능
'Technology',
'Sports',
'Music',
'Art',
'Travle',
'Food',
'Fashion',
'Science'
) NOT NULL,
bio TEXT NOT NULL, -- 무작정 긴 텍스트를 받을 수 있는 타입이 아니라 자신의 데이터가 들어가기에 가장 가벼운 타입을 고르는 게 좋음 (타입에 따라 데이터를 저장하는 방식이 다르고, 성능 차이가 생김)
profile_picture TINYBLOB, -- 바이트를 저장. 사진이나 해시 또는 파일 전체 저장 가능
age TINYINT UNSIGNED NOT NULL, -- 작은 공간을 차지하는 정수
is_admin BOOLEAN DEFAULT FALSE NOT NULL, -- 참이면 1, 거짓이면 0 저장
balance FLOAT DEFAULT 0.0 NOT NULL, -- FLOAT: 저장하고 싶은 실수 마음대로. DECIMAL(숫자 전체 개수, 소수점 뒤 자리 수): ex) DECIMAL(5,2) => 숫자 전체 5자리이고 소수점 뒤 2자리 (ex. 999.12)
joined_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL, -- DATETIME 둘 다 YYY-MM-DD hh:mm:ss 형태로 저장. DATETIME은 TIMESTAMP보다 더 공간을 차지. TIMESTAMTIMESTAMP은 계정 타임존에 종속. DEFAULT CURRENT_TIMESTAMP: 테이블 생성될 때 시각을 기록
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP NOT NULL, -- 테이블을 생성할 때 updated_at 컬럼에 현재 시각을 저장하고 테이블을 업데이트 할 때도 컬럼에 업데이트 시간을 기록
birth_date DATE NOT NULL, -- DATETIME과 비슷. 다만 연도, 월, 일까지만
bed_time TIME NOT NULL, -- 시간, 분, 초까지만
graduation_year YEAR NOT NULL, -- 1901~2155
-- 동일한 제약조건이 여러 컬럼에 적용될 때 편함
CONSTRAINT chk_age CHECK (age < 100),
CONSTRAINT uq_email UNIQUE (email, username)
)
- 테이블 행을 고유하게 식별하도록 해줌
- 기본키 컬럼은 고유해야 하고 변경 불가능 해야함
👉 서로 다른 행 값 중복 x
👉 수정 x- 자연 기본키(natural pk): 데이터에서 파생되어 고유 식별자로 사용하는 컬럼. 테이블 데이터와 논리적 관계 o (ex. title)
- 대체 기본키(surrogate pk): 어떤 데이터와 관련없이 고유 식별자를 만들기 위해 인위적으로 사용하는 컬럼. 다른 컬럼과 논리적 관계 x (ex. movie_id)
- 대체 기본키 사용을 권장. 자연 기본키는 불변하고 고유하게 유지하기 어려움
- NULL 허용 여부:
- PRIMARY KEY: NULL 값을 허용하지 않습니다.
- UNIQUE: NULL 값을 허용할 수 있습니다 (대부분의 데이터베이스에서).
- 테이블당 개수:
- PRIMARY KEY: 테이블당 하나만 가질 수 있습니다.
- UNIQUE: 테이블에 여러 개의 UNIQUE 제약 조건을 가질 수 있습니다.
- 인덱스 생성:
- PRIMARY KEY: 자동으로 클러스터드 인덱스를 생성합니다 (대부분의 DBMS에서).
- UNIQUE: 논-클러스터드 인덱스를 생성합니다.
- 레코드 식별:
- PRIMARY KEY: 테이블의 각 레코드를 고유하게 식별하는 데 사용됩니다.
- UNIQUE: 특정 열의 값이 고유함을 보장하지만, 반드시 레코드 식별용은 아닙니다.
- 외래 키 참조:
- PRIMARY KEY: 다른 테이블의 외래 키가 참조할 수 있습니다.
- UNIQUE: 외래 키의 참조 대상이 될 수 있지만, PRIMARY KEY만큼 일반적이지 않습니다.
- 변경 가능성:
- PRIMARY KEY: 일반적으로 변경을 권장하지 않습니다 (변경 시 다른 테이블의 참조 무결성에 영향을 줄 수 있음).
- UNIQUE: PRIMARY KEY에 비해 상대적으로 변경이 용이할 수 있지만, 여전히 주의가 필요합니다.
결론적으로, UNIQUE가 PRIMARY KEY보다 변경이 더 쉽다고 볼 수는 있지만, 이는 주요 차이점 중 하나일 뿐입니다. 두 제약 조건의 역할과 특성에는 더 많은 차이가 있습니다.