MSSQL 1.4 · 1부. 기초

데이터 형식

int·decimal·nvarchar·datetime2 가운데 무엇을 선택해야 하는지 봅니다. 한글이 깨지는 자리도 함께 봅니다.

예상 학습 시간 18분 난이도 입문
개념 설명

형식을 미리 정하는 까닭

테이블을 만들 때 열마다 형식을 적었습니다. 값을 넣을 때 정하지 않고 미리 못 박아 두는 데는 까닭이 있습니다.

  • 잘못된 값을 막습니다. 숫자 자리에 글자를 넣으면 저장되지 않고 거부됩니다. 들어간 뒤에 찾아내는 것보다 못 들어가게 하는 편이 훨씬 쌉니다.
  • 자리를 아낍니다. 1 부터 200 까지만 담을 열에 8바이트를 사용할 이유가 없습니다. 행이 수백만이 되면 이 차이가 디스크와 메모리에 그대로 나타납니다.
  • 셈하는 방법이 정해집니다. 같은 1 이라도 숫자면 더할 수 있고 글자면 이어 붙습니다.
상세 사용법

숫자

정수는 담을 수 있는 범위가 다릅니다. 필요한 만큼만 선택하면 됩니다.

형식크기범위
tinyint1바이트0 ~ 255
smallint2바이트-32,768 ~ 32,767
int4바이트약 -21억 ~ 21억
bigint8바이트약 -922경 ~ 922경

고민되면 int 입니다. 게시글 번호나 회원 번호는 21억을 넘기기 어렵고, 넘길 것 같으면 그때 bigint 를 선택하면 됩니다.

소수 — decimal 과 float 은 다릅니다

소수를 담는 형식이 둘인데 셈한 결과가 다릅니다. 0.1 과 0.2 를 더해 보면 차이가 그대로 드러납니다.

SQL
SELECT CAST(0.1 AS DECIMAL(10,2)) + CAST(0.2 AS DECIMAL(10,2)) AS dec_sum,
       CAST(0.1 AS FLOAT) + CAST(0.2 AS FLOAT) AS float_sum;
결과
dec_sumfloat_sum
.300.30000000000000004
(1개 행이 영향을 받음)

float 은 2진수로 값을 담기 때문에 0.1 을 정확히 나타내지 못합니다. 그래서 더한 값이 0.3 이 아니고, 0.3 과 같은지 비교하면 다르다고 나옵니다.

돈과 수량에는 decimal 을 사용하십시오. DECIMAL(10, 2) 는 전체 10자리에 소수점 아래 2자리라는 뜻입니다. float 은 오차를 받아들일 수 있는 자리(좌표·측정값)에 사용합니다.

최소 예제

문자 — 한글을 담으려면

문자 형식은 이름 앞에 n 이 붙는 것과 안 붙는 것으로 나뉩니다. 이 차이가 한글을 담을 수 있는지를 구분합니다.

SQL
DECLARE @v VARCHAR(20), @n NVARCHAR(20);

SET @v = '홍길동';      -- N 을 붙이지 않았습니다
SET @n = N'홍길동';

SELECT @v AS varchar_no_N, @n AS nvarchar_with_N,
       DATALENGTH(@v) AS v_bytes, DATALENGTH(@n) AS n_bytes;
결과
varchar_no_Nnvarchar_with_Nv_bytesn_bytes
???홍길동36
(1개 행이 영향을 받음)

글자가 ??? 로 바뀌었습니다. 오류가 나지 않고 조용히 망가진 것이라 더 나쁩니다. 바이트 수를 보면 무슨 일이 있었는지 알 수 있습니다 — 한 글자가 1바이트로 눌리면서 담지 못하는 글자가 물음표로 대체됐습니다.

되돌릴 수 없습니다. 이미 ??? 가 되어 저장된 값은 원래 글자를 알 방법이 없습니다.

형식한 글자담을 수 있는 것
char(n)1바이트영문·숫자. 길이를 채워 저장합니다
varchar(n)1바이트영문·숫자. 넣은 만큼만 차지합니다
nchar(n)2바이트모든 글자. 길이를 채워 저장합니다
nvarchar(n)2바이트모든 글자. 넣은 만큼만 차지합니다

char(10)abc 를 넣으면 10바이트를 차지하고, varchar(10) 은 3바이트만 차지합니다. 길이가 늘 같은 값(우편번호·주민번호 형태)이 아니면 varchar 계열을 선택하십시오.

실습 데이터가 그렇게 나뉜 까닭

Member.USERS 의 세 열을 보면 규칙이 보입니다.

형식까닭
user_idvarchar(50)로그인 아이디는 영문과 숫자만 받습니다
emailvarchar(200)전자 메일 주소도 영문입니다
nicknamenvarchar(50)한글이 들어갑니다

사람이 자유롭게 적는 자리는 nvarchar 로 두십시오. 아이디처럼 규칙을 강제하는 자리만 varchar 로 아낍니다.

상세 사용법

날짜와 시간

같은 값을 형식만 바꿔 담아 보면 무엇을 버리고 무엇을 남기는지 드러납니다. 괄호 안의 숫자는 소수점 아래 몇 자리까지 남길지입니다.

SQL
SELECT CAST('2026-01-01 09:30:45.1234567' AS DATETIME2(0)) AS dt2_0,
       CAST('2026-01-01 09:30:45.1234567' AS DATETIME2(3)) AS dt2_3,
       CAST('2026-01-01 09:30:45.1234567' AS DATETIME2(7)) AS dt2_7,
       CAST('2026-01-01 09:30:45.1234567' AS DATE)         AS d_only;
결과
dt2_0dt2_3dt2_7d_only
2026-01-01 09:30:452026-01-01 09:30:45.1232026-01-01 09:30:45.12345672026-01-01
(1개 행이 영향을 받음)
형식크기담는 것
date3바이트날짜만. 생일·기념일에 알맞습니다
time(n)3~5바이트시각만
datetime2(n)6~8바이트날짜와 시각. 지금 사용하는 기본입니다
datetimeoffset8~10바이트시간대까지 함께. 여러 나라에서 사용하는 서비스에 필요합니다
datetime8바이트옛 형식입니다. 새로 만들 때는 선택하지 마십시오

datetime 을 피하라는 데는 까닭이 있습니다. 같은 값을 넣어 보면 변환 자체가 실패합니다.

SQL
SELECT CAST('2026-01-01 09:30:45.1234567' AS DATETIME) AS dt_old;
오류
메시지 241, 수준 16, 상태 1 Conversion failed when converting date and/or time from character string.

datetime 은 소수점 아래를 3자리까지만 받고, 그것도 1/300초 단위로 반올림합니다. 정확히 담기지 않는 시각이 생깁니다. 새로 만드는 테이블에는 datetime2 를 사용하십시오. 실습 데이터베이스도 그렇게 되어 있습니다.

상세 사용법

그 밖에 자주 사용하는 것

형식크기담는 것
bit1비트참·거짓을 1 과 0 으로. 실습 데이터의 use_reply 가 이것입니다
uniqueidentifier16바이트GUID. 여러 서버에서 겹치지 않는 번호가 필요할 때(3.2)
varbinary(n)넣은 만큼파일 같은 이진 값. 대개는 파일을 밖에 두고 경로만 담습니다

bit 는 NULL 도 가질 수 있습니다. 참·거짓·모름 세 가지가 되므로, 반드시 둘 중 하나여야 한다면 NOT NULL 을 함께 적으십시오.

상세 사용법

형식이 맞지 않으면

맞지 않는 값은 조용히 들어가지 않고 오류로 막힙니다. 두 가지가 자주 나옵니다.

SQL
DECLARE @i INT = CAST(N'열' AS INT);
오류
메시지 245 Conversion failed when converting the nvarchar value '열' to data type int.
SQL
DECLARE @s SMALLINT = 40000;
오류
메시지 220 Arithmetic overflow error for data type smallint, value = 40000.

smallint 의 끝이 32,767 이라 40,000 이 들어가지 못했습니다. 형식을 좁게 잡으면 이런 자리에서 막힙니다. 자리를 아끼는 것과 나중에 늘릴 여지를 두는 것 사이에서 선택하는 일이고, 대개는 int 로 두는 편이 뒤탈이 없습니다.

메시지 글귀는 설치한 언어를 따릅니다. 번호(241 · 245 · 220)는 어디서나 같습니다.

실습 문제

직접 해보기

1. 형식 선택하기 난이도 하

상품 테이블에 담을 다음 값들에 어떤 형식이 알맞을지 선택해 보세요. 상품명(한글 100자 이내) · 가격(원 단위, 소수 없음) · 무게(소수점 아래 2자리) · 품절 여부 · 등록 일시.

한글이 들어가는 자리와 셈해야 하는 자리를 먼저 구분해 보십시오. 값을 비교하거나 더할 것이라면 float 은 피합니다.
상품명 NVARCHAR(100) -- 한글이 들어갑니다 가격 INT -- 원 단위라 소수가 없습니다 무게 DECIMAL(6, 2) -- 소수를 셈하므로 float 이 아닙니다 품절 여부 BIT NOT NULL -- 둘 중 하나여야 하므로 NOT NULL 등록 일시 DATETIME2(0) -- 초까지면 충분합니다
2. 깨지는 것 확인하기 난이도 중

varchar(20) 변수에 한글을 넣어 ??? 가 되는 것을 직접 보고, nvarchar 로 바꾸면 제대로 담기는 것도 확인해 보세요. 각각 몇 바이트를 차지하는지도 함께 재 보십시오.

DECLARE @a VARCHAR(20) = '가나다'; DECLARE @b NVARCHAR(20) = N'가나다'; SELECT @a AS broken, @b AS ok, DATALENGTH(@a) AS a_bytes, -- 3 DATALENGTH(@b) AS b_bytes; -- 6 -- @a 는 ??? 로 나옵니다. -- N 을 붙여도 VARCHAR 변수에 담는 순간 같은 일이 벌어집니다. -- 담는 쪽 형식이 NVARCHAR 여야 합니다.
요약
  • 정수는 int 가 기본입니다. 21억을 넘길 것 같을 때만 bigint 입니다.
  • 돈과 수량은 decimal 입니다. float 은 0.1 + 0.2 가 0.3 이 되지 않습니다.
  • 한글이 들어가는 자리는 nvarchar 이고, 값 앞에 N 을 붙입니다. varchar 에 넣으면 오류 없이 ??? 로 망가집니다.
  • 날짜는 datetime2 입니다. 옛 datetime 은 소수점 아래를 1/300초로 반올림합니다.
  • 맞지 않는 값은 오류로 막힙니다 — 변환 실패는 245, 범위 초과는 220 입니다.