문자열 데이터 형식 (String Data Types)
VARCHAR vs NVARCHAR - 차이점
| 구분 | VARCHAR | NVARCHAR |
| 문자 인코딩 | ANSI/ASCII (1바이트) | Unicode UTF-16 (2바이트) |
| 저장 공간 | 문자당 1바이트 | 문자당 2바이트 |
| 최대 길이 | 8,000자 | 4,000자 |
| 다국어 지원 | 제한적 | 완벽 지원 |
| 성능 | 빠름 | 상대적으로 느림 |
VARCHAR 예제
-- VARCHAR 사용 (영문, 숫자 중심)
CREATE TABLE users_varchar (
id INT IDENTITY(1,1) PRIMARY KEY,
username VARCHAR(50), -- 최대 50자
email VARCHAR(100), -- 최대 100자
description VARCHAR(MAX) -- 최대 2GB
);
INSERT INTO users_varchar VALUES
('john_doe', 'john@email.com', 'Simple description');
NVARCHAR 예제
-- NVARCHAR 사용 (다국어 지원)
CREATE TABLE users_nvarchar (
id INT IDENTITY(1,1) PRIMARY KEY,
username NVARCHAR(50), -- 최대 50자 (유니코드)
korean_name NVARCHAR(20), -- 한글 이름
description NVARCHAR(MAX) -- 최대 2GB
);
INSERT INTO users_nvarchar VALUES
(N'홍길동', N'홍길동', N'안녕하세요. 한글 설명입니다.');
-- 주의: 유니코드 문자열은 앞에 N을 붙여야 함!
기타 문자열 형식
-- 고정 길이 문자열
CHAR(10) -- 항상 10바이트 (공백으로 패딩)
NCHAR(10) -- 항상 20바이트 (유니코드, 공백으로 패딩)
-- 대용량 텍스트 (레거시, 사용 권장하지 않음)
TEXT -- 최대 2GB (VARCHAR(MAX) 사용 권장)
NTEXT -- 최대 2GB (NVARCHAR(MAX) 사용 권장)
숫자 데이터 형식 (Numeric Data Types)
정수형
-- 정수 데이터 형식
TINYINT -- 0 ~ 255 (1바이트)
SMALLINT -- -32,768 ~ 32,767 (2바이트)
INT -- -2,147,483,648 ~ 2,147,483,647 (4바이트)
BIGINT -- 매우 큰 정수 (8바이트)
-- 예제
CREATE TABLE number_examples (
tiny_col TINYINT, -- 나이, 개수 등
small_col SMALLINT, -- 연도, 작은 ID
int_col INT, -- 일반적인 ID, 수량
big_col BIGINT -- 큰 ID, 금액(원 단위)
);
실수형
-- 실수 데이터 형식
FLOAT -- 근사값 (4바이트 또는 8바이트)
REAL -- 근사값 (4바이트, FLOAT(24)와 동일)
DECIMAL(p,s) -- 정확한 값 (p: 전체자리수, s: 소수점자리수)
NUMERIC(p,s) -- DECIMAL과 동일
-- 예제
CREATE TABLE decimal_examples (
price DECIMAL(10,2), -- 가격: 12345678.99
ratio DECIMAL(5,4), -- 비율: 1.2345
weight FLOAT, -- 무게 (근사값)
temperature REAL -- 온도 (근사값)
);
INSERT INTO decimal_examples VALUES
(1234.56, 0.7525, 75.6, 36.5);
날짜/시간 데이터 형식 (Date and Time Types)
주요 날짜/시간 형식
-- 날짜/시간 데이터 형식
DATE -- 날짜만: YYYY-MM-DD
TIME -- 시간만: HH:MM:SS.nnnnnnn
DATETIME -- 날짜+시간: 1753-01-01 ~ 9999-12-31 (정밀도: 3.33ms)
DATETIME2 -- 향상된 날짜+시간 (정밀도: 100ns)
SMALLDATETIME -- 작은 날짜+시간: 1900-01-01 ~ 2079-06-06 (정밀도: 1분)
DATETIMEOFFSET -- 시간대 정보 포함
-- 예제
CREATE TABLE datetime_examples (
birth_date DATE, -- 생년월일
work_time TIME, -- 근무 시간
created_at DATETIME, -- 생성일시 (레거시)
updated_at DATETIME2, -- 수정일시 (권장)
appointment SMALLDATETIME, -- 약속 시간
event_time DATETIMEOFFSET -- 글로벌 이벤트 시간
);
INSERT INTO datetime_examples VALUES
('1990-05-15', -- 날짜
'09:30:00', -- 시간
'2024-01-15 14:30:25.123', -- 날짜시간
'2024-01-15 14:30:25.1234567', -- 고정밀 날짜시간
'2024-01-15 15:00', -- 소형 날짜시간
'2024-01-15 15:00:00.0000000 +09:00' -- 시간대 포함
);
날짜 관련 함수
-- 현재 날짜/시간 함수
SELECT GETDATE() AS current_datetime; -- 현재 날짜시간
SELECT GETUTCDATE() AS utc_datetime; -- UTC 날짜시간
SELECT SYSDATETIME() AS sys_datetime2; -- 시스템 DATETIME2
-- 날짜 계산
SELECT DATEADD(DAY, 7, GETDATE()) AS next_week; -- 7일 후
SELECT DATEADD(MONTH, -1, GETDATE()) AS last_month; -- 1개월 전
SELECT DATEDIFF(DAY, '2024-01-01', GETDATE()) AS days_passed; -- 경과일
-- 날짜 부분 추출
SELECT YEAR(GETDATE()) AS current_year;
SELECT MONTH(GETDATE()) AS current_month;
SELECT DAY(GETDATE()) AS current_day;
이진 데이터 형식 (Binary Data Types)
-- 이진 데이터 형식
BINARY(n) -- 고정 길이 이진 데이터
VARBINARY(n) -- 가변 길이 이진 데이터
VARBINARY(MAX) -- 대용량 이진 데이터 (최대 2GB)
IMAGE -- 레거시, VARBINARY(MAX) 사용 권장
-- 예제
CREATE TABLE binary_examples (
file_hash BINARY(32), -- SHA-256 해시 (32바이트 고정)
thumbnail VARBINARY(MAX), -- 썸네일 이미지
document VARBINARY(MAX) -- 문서 파일
);
기타 특수 데이터 형식
UNIQUEIDENTIFIER (GUID)
-- GUID 데이터 형식
CREATE TABLE guid_example (
id UNIQUEIDENTIFIER DEFAULT NEWID() PRIMARY KEY,
name NVARCHAR(100)
);
INSERT INTO guid_example (name) VALUES (N'테스트');
SELECT * FROM guid_example;
-- 결과: 12345678-1234-1234-1234-123456789012 형태
BIT (부울)
-- 부울 데이터 형식
CREATE TABLE bool_example (
id INT IDENTITY(1,1),
is_active BIT DEFAULT 1, -- 1(TRUE) 또는 0(FALSE)
is_deleted BIT DEFAULT 0
);
INSERT INTO bool_example (is_active, is_deleted) VALUES
(1, 0), -- TRUE, FALSE
(0, 1); -- FALSE, TRUE
MONEY
-- 화폐 데이터 형식
CREATE TABLE money_example (
product_id INT,
price MONEY, -- -922,337,203,685,477.5808 ~ 922,337,203,685,477.5807
discount SMALLMONEY -- -214,748.3648 ~ 214,748.3647
);
INSERT INTO money_example VALUES
(1, 1234.56, 100.00);
데이터 형식 선택 가이드
문자열 선택 기준
-- 영문 위주 + 성능 중시 → VARCHAR
username VARCHAR(50)
-- 다국어 지원 필요 → NVARCHAR
korean_name NVARCHAR(50)
-- 대용량 텍스트 → MAX 사용
content NVARCHAR(MAX)
-- 고정 길이 (성능 최적화) → CHAR/NCHAR
country_code CHAR(2) -- 'KR', 'US' 등
숫자 선택 기준
-- 작은 정수 (0~255) → TINYINT
age TINYINT
-- 일반 정수 → INT
user_id INT
-- 큰 정수 → BIGINT
transaction_id BIGINT
-- 정확한 소수점 → DECIMAL
price DECIMAL(10,2)
-- 근사값 계산 → FLOAT
scientific_value FLOAT
날짜/시간 선택 기준
-- 날짜만 필요 → DATE
birth_date DATE
-- 시간만 필요 → TIME
work_start_time TIME
-- 일반적인 날짜시간 → DATETIME2 (권장)
created_at DATETIME2 DEFAULT GETDATE()
-- 글로벌 시스템 → DATETIMEOFFSET
global_event_time DATETIMEOFFSET
성능 및 저장공간 고려사항
저장공간 최적화
-- 공간 효율적인 설계
CREATE TABLE optimized_table (
id INT IDENTITY(1,1) PRIMARY KEY,
-- 문자열: 적절한 길이 지정
username VARCHAR(30), -- NVARCHAR(30)보다 절반 용량
-- 숫자: 범위에 맞는 타입 선택
age TINYINT, -- INT보다 75% 절약
status TINYINT, -- 상태코드 (0~255)
-- 날짜: 용도에 맞는 타입
birth_date DATE, -- DATETIME2보다 용량 절약
-- 부울: BIT 사용
is_active BIT DEFAULT 1 -- TINYINT보다 공간 절약
);
인덱스 고려사항
-- 인덱스에 유리한 데이터 타입 선택
CREATE TABLE indexed_table (
id INT IDENTITY(1,1) PRIMARY KEY,
-- 고정 길이가 인덱스 성능에 유리
product_code CHAR(10),
-- 가변 길이는 적절한 크기로
description VARCHAR(500) -- VARCHAR(MAX)는 인덱스 불가
);
-- 복합 인덱스에서 크기가 작은 컬럼을 앞에
CREATE INDEX IX_composite ON indexed_table (product_code, id);
마무리
MSSQL의 데이터 형식을 올바르게 선택하면:
- 저장공간 최적화
- 쿼리 성능 향상
- 데이터 무결성 보장
- 개발 효율성 증대
특히 VARCHAR vs NVARCHAR 선택은 다국어 지원 필요성과 성능을 고려하여 신중하게 결정해야 합니다.