데이터 형식
int·decimal·nvarchar·datetime2 가운데 무엇을 선택해야 하는지 봅니다. 한글이 깨지는 자리도 함께 봅니다.
형식을 미리 정하는 까닭
테이블을 만들 때 열마다 형식을 적었습니다. 값을 넣을 때 정하지 않고 미리 못 박아 두는 데는 까닭이 있습니다.
- 잘못된 값을 막습니다. 숫자 자리에 글자를 넣으면 저장되지 않고 거부됩니다. 들어간 뒤에 찾아내는 것보다 못 들어가게 하는 편이 훨씬 쌉니다.
- 자리를 아낍니다. 1 부터 200 까지만 담을 열에 8바이트를 사용할 이유가 없습니다. 행이 수백만이 되면 이 차이가 디스크와 메모리에 그대로 나타납니다.
- 셈하는 방법이 정해집니다. 같은 1 이라도 숫자면 더할 수 있고 글자면 이어 붙습니다.
숫자
정수는 담을 수 있는 범위가 다릅니다. 필요한 만큼만 선택하면 됩니다.
| 형식 | 크기 | 범위 |
|---|---|---|
| tinyint | 1바이트 | 0 ~ 255 |
| smallint | 2바이트 | -32,768 ~ 32,767 |
| int | 4바이트 | 약 -21억 ~ 21억 |
| bigint | 8바이트 | 약 -922경 ~ 922경 |
고민되면 int 입니다. 게시글 번호나 회원 번호는 21억을 넘기기 어렵고, 넘길 것 같으면 그때 bigint 를 선택하면 됩니다.
소수 — decimal 과 float 은 다릅니다
소수를 담는 형식이 둘인데 셈한 결과가 다릅니다. 0.1 과 0.2 를 더해 보면 차이가 그대로 드러납니다.
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_sum | float_sum |
|---|---|
| .30 | 0.30000000000000004 |
float 은 2진수로 값을 담기 때문에 0.1 을 정확히 나타내지
못합니다. 그래서 더한 값이 0.3 이 아니고, 0.3 과 같은지 비교하면 다르다고
나옵니다.
돈과 수량에는 decimal 을 사용하십시오.
DECIMAL(10, 2) 는 전체 10자리에 소수점 아래 2자리라는 뜻입니다.
float 은 오차를 받아들일 수 있는 자리(좌표·측정값)에 사용합니다.
문자 — 한글을 담으려면
문자 형식은 이름 앞에 n 이 붙는 것과 안 붙는 것으로 나뉩니다. 이 차이가 한글을 담을 수 있는지를 구분합니다.
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_N | nvarchar_with_N | v_bytes | n_bytes |
|---|---|---|---|
| ??? | 홍길동 | 3 | 6 |
글자가 ??? 로 바뀌었습니다. 오류가 나지 않고 조용히 망가진 것이라 더 나쁩니다. 바이트 수를 보면 무슨 일이 있었는지 알 수 있습니다 — 한 글자가 1바이트로 눌리면서 담지 못하는 글자가 물음표로 대체됐습니다.
되돌릴 수 없습니다. 이미 ??? 가 되어 저장된 값은 원래 글자를 알 방법이 없습니다.
| 형식 | 한 글자 | 담을 수 있는 것 |
|---|---|---|
| char(n) | 1바이트 | 영문·숫자. 길이를 채워 저장합니다 |
| varchar(n) | 1바이트 | 영문·숫자. 넣은 만큼만 차지합니다 |
| nchar(n) | 2바이트 | 모든 글자. 길이를 채워 저장합니다 |
| nvarchar(n) | 2바이트 | 모든 글자. 넣은 만큼만 차지합니다 |
char(10) 에 abc 를 넣으면 10바이트를
차지하고, varchar(10) 은 3바이트만 차지합니다. 길이가 늘
같은 값(우편번호·주민번호 형태)이 아니면 varchar 계열을
선택하십시오.
실습 데이터가 그렇게 나뉜 까닭
Member.USERS 의 세 열을 보면 규칙이 보입니다.
| 열 | 형식 | 까닭 |
|---|---|---|
| user_id | varchar(50) | 로그인 아이디는 영문과 숫자만 받습니다 |
| varchar(200) | 전자 메일 주소도 영문입니다 | |
| nickname | nvarchar(50) | 한글이 들어갑니다 |
사람이 자유롭게 적는 자리는 nvarchar 로 두십시오. 아이디처럼 규칙을 강제하는 자리만 varchar 로 아낍니다.
날짜와 시간
같은 값을 형식만 바꿔 담아 보면 무엇을 버리고 무엇을 남기는지 드러납니다. 괄호 안의 숫자는 소수점 아래 몇 자리까지 남길지입니다.
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_0 | dt2_3 | dt2_7 | d_only |
|---|---|---|---|
| 2026-01-01 09:30:45 | 2026-01-01 09:30:45.123 | 2026-01-01 09:30:45.1234567 | 2026-01-01 |
| 형식 | 크기 | 담는 것 |
|---|---|---|
| date | 3바이트 | 날짜만. 생일·기념일에 알맞습니다 |
| time(n) | 3~5바이트 | 시각만 |
| datetime2(n) | 6~8바이트 | 날짜와 시각. 지금 사용하는 기본입니다 |
| datetimeoffset | 8~10바이트 | 시간대까지 함께. 여러 나라에서 사용하는 서비스에 필요합니다 |
| datetime | 8바이트 | 옛 형식입니다. 새로 만들 때는 선택하지 마십시오 |
옛 datetime 을 피하라는 데는 까닭이 있습니다. 같은 값을 넣어
보면 변환 자체가 실패합니다.
SELECT CAST('2026-01-01 09:30:45.1234567' AS DATETIME) AS dt_old;
datetime 은 소수점 아래를 3자리까지만 받고, 그것도
1/300초 단위로 반올림합니다. 정확히 담기지 않는 시각이 생깁니다.
새로 만드는 테이블에는 datetime2 를 사용하십시오. 실습
데이터베이스도 그렇게 되어 있습니다.
그 밖에 자주 사용하는 것
| 형식 | 크기 | 담는 것 |
|---|---|---|
| bit | 1비트 | 참·거짓을 1 과 0 으로. 실습 데이터의 use_reply 가 이것입니다 |
| uniqueidentifier | 16바이트 | GUID. 여러 서버에서 겹치지 않는 번호가 필요할 때(3.2) |
| varbinary(n) | 넣은 만큼 | 파일 같은 이진 값. 대개는 파일을 밖에 두고 경로만 담습니다 |
bit 는 NULL 도 가질 수 있습니다. 참·거짓·모름
세 가지가 되므로, 반드시 둘 중 하나여야 한다면
NOT NULL 을 함께 적으십시오.
형식이 맞지 않으면
맞지 않는 값은 조용히 들어가지 않고 오류로 막힙니다. 두 가지가 자주 나옵니다.
DECLARE @i INT = CAST(N'열' AS INT);
DECLARE @s SMALLINT = 40000;
smallint 의 끝이 32,767 이라 40,000 이 들어가지 못했습니다.
형식을 좁게 잡으면 이런 자리에서 막힙니다. 자리를 아끼는 것과 나중에
늘릴 여지를 두는 것 사이에서 선택하는 일이고, 대개는 int 로
두는 편이 뒤탈이 없습니다.
메시지 글귀는 설치한 언어를 따릅니다. 번호(241 · 245 · 220)는 어디서나 같습니다.
직접 해보기
상품 테이블에 담을 다음 값들에 어떤 형식이 알맞을지 선택해 보세요. 상품명(한글 100자 이내) · 가격(원 단위, 소수 없음) · 무게(소수점 아래 2자리) · 품절 여부 · 등록 일시.
varchar(20) 변수에 한글을 넣어 ??? 가 되는 것을 직접 보고, nvarchar 로 바꾸면 제대로 담기는 것도 확인해 보세요. 각각 몇 바이트를 차지하는지도 함께 재 보십시오.
- 정수는 int 가 기본입니다. 21억을 넘길 것 같을 때만 bigint 입니다.
- 돈과 수량은 decimal 입니다.
float은 0.1 + 0.2 가 0.3 이 되지 않습니다. - 한글이 들어가는 자리는 nvarchar 이고, 값 앞에
N을 붙입니다. varchar 에 넣으면 오류 없이 ??? 로 망가집니다. - 날짜는 datetime2 입니다. 옛
datetime은 소수점 아래를 1/300초로 반올림합니다. - 맞지 않는 값은 오류로 막힙니다 — 변환 실패는 245, 범위 초과는 220 입니다.