Post

4.1 Data Types (SQL)

Chapter 4에서는 SQL에서 다루는 자료형과 관련된 함수에 대해서 알아본다. WHERE절을 사용하여 값을 비교할 때 어떤 경우에는 따옴표 (‘)를 붙이고, 어떤 경우에는 안붙이는지, 그리고 날짜를 비교할 떄 왜 YYYY-MM-DD와 같은 형태로 쿼리문을 작성하는지 궁금했다면, Chapter 4를 통해 궁금증을 해소할 수 있다.

Data Types

프로그래밍 경험이 있다면, data type은 친숙한 개념일 것이다. Data type은 SQL에서 데이터를 다루기위한 유형을 뷴류해놓은 개념이다. 데이터의 유형을 나누는 이유는, 데이터의 성격에따라 저장하는 공간의 사이즈 혹은 형태를 다르게 결정하고, 이에따라 저장공간을 효율적으로 사용할 수 있기 때문이다. 기본적으로 서로 다른 데이터 타입간의 비교와 연산은 불가능하다. 하지만, 형변환을 통해 같은 데이터 타입으로 맞춰주면 비교와 연산이 가능하다.

SQL의 데이터타입은 크게 4가지로 분류할 수 있다.

  • 문자 타입 (String type)
  • 숫자 타입 (Numeric type)
  • 시간 타입 (Temporal type)
  • 기타

문자 타입

문자 타입은 문자/문자열을 표현하기 위한 데이터 타입이다. 따옴표 (‘)를 통해서 정의한다:

1
SELECT 'string type';

문자 타입은 고정길이 문자열과 가변길이 문자열로 분류할 수 있다. 고정길이 문자열은 저장하는데 항상 같은 공간을 필요로한다. 만약 더 짧은 문자열을 입력한다면 남은 공간은 공백으로 채워진다. 가변길이 문자열은 저장하려는 문자열의 길이에 따라 가변으로 저장공간을 할당한다. 저장공간을 효율적으로 사용할 수 있지만, 데이터 처리시에 길이를 확인해야하기 떄문에 고정길이 문자열에 비해 연산 오버헤드가 발생한다. 대표적인 문자열 타입에는 다음의 종류가 있다:

자료형문자수고정/가변
char(n)n고정길이
varchar(n)최대 n가변길이
text(n)최대 n가변길이

숫자 타입

숫자 타입은 정수와 소수와 같은 숫자 값을 표현하기 위한 데이터 타입이다. 숫자 타입은 정수 타입과 소수 타입으로 분류할 수 있다. 별다른 특수기호 없이 숫자 값을 이용하여 정의할 수 있다:

1
2
3
4
-- 정수 타입
SELECT 10;
-- 소수 타입
SELECT 1.23;

숫자 타입은 타입별로 다른 저장공간을 갖기 때문에 표현할 수 있는 값의 범위가 달라진다. 값을 표현할 때 overflow가 발생하기 않도록 적절한 자료형을 선택해야한다.

자료형정수/소수저장공간표현 범위
smallint정수2 bytes-32,768 ~ 32,767
integer정수4 bytes-2,147,483,648 ~ 2,147,483,647
bigint정수8 bytes-9,223,372,036,854,775,808 ~ 9,223,372,036,854,775,807
float소수4 bytes-3.4E38 ~ 3.4E38
double소수8 bytes-1.7E308 ~ 1.7E308

시간 타입

시간 타입은 시간/날짜를 표현하기 위한 타입이다. 고정적인 저장공간을 가졌으며, ‘YYYY-MM-DD HH:MI:SS’와 같은 형태로 값을 표현할 수 있다.

1
2
3
4
-- date 값의 표현
SELECT '2022-03-01';
-- timestamp 값의 표현
SELECT '2022-01-01 12:34:56';
자료형저장공간표현 값
date4 bytes날짜
timestamp8 bytes날짜 + 시간
interval8 bytestimestamp의 간격

Etc.

이 외에도 SQL에서는 다양한 데이터 타입을 지원한다.

  • boolean
  • UUID
  • JSON
  • HStore
  • 사용자 정의 자료형

형변환 (Type Casting)

기본적으로 다른 데이터 타입의 값끼리는 비교나 연산이 불가능하다. 하지만 형변환을 통해 데이터 타입을 변경한다면 비교와 연산이 가능해진다. 그리고 형변환을 하지 않았더라도 특정한 포맷으로 입력했다면, 다른 데이터 타입간의 비교가 가능한 경우도 있다. 이는 데이터베이스 내부적으로 암시적 형변환이 동작했기 때문이다. 아래는 비교 가능한 경우와 비교가 불가능한 경우를 예시를 통해서 설명한다.

숫자 타입 vs 문자열 타입

1
2
3
4
5
6
SELECT 1 < 2;
-- 예제 1 결과: TRUE
SELECT 1 < '이';
-- 예제 2 결과: Error
SELECT 3 < '1';
-- 예제 3 결과: FALSE
  • 예제 1: 1과 2를 비교하는 첫 번째 결과는 TRUE이다.
  • 예제 2: 이는 다른 데이터 타입을 갖는 값끼리는 비교가 불가능하기 때문에 error가 발생.
  • 예제 3: 숫자 3과 문자로된 숫자 1을 비교하는 query의 결과로는 정상 동작 결과인 FALSE를 반환. SQL엔진 내부에서 암시적으로 형변환을 진행했기 때문.

시간 타입 vs 문자열 타입

1
2
3
4
SELECT now() < '2099-12-31';
-- 예제 1 결과: TRUE
SELECT now() < '2099'; 
-- 예제 2 결과: Error

now는 현재 시각에 해당하는 timestamp를 반환하는 함수입니다.

  • 예제 1: timestamp와 2099-12-31과 같이 년도-월-일에 순서에 맞춘 문자열을 비교한다면, 오류 없이 query가 실행됨.
  • 예제 2: 년도를 나타내는 2099만을 넣어서 query를 실행하면 오류가 발생합니다. 이는 문자열을 시간 타입으로 변환하기 위해서는 특정한 포맷을 만족시켜야하기 떄문.

Boolean vs Others

1
2
3
4
SELECT FALSE = 1;
-- 예제 1 결과: Error
SELECT TRUE = 'TRUE';
-- 예제 2 결과: TRUE
  • 예제 1: boolean타입은 내부적으로는 0, 1로 동작하겠지만 숫자 타입과는 비교가 되지 않음.
  • 예제 2: 문자열로 TRUE, FALSE를 적어준다면 캐스팅되어 오류 없이 동작.

형변환 함수

암시적인 타입 변환은 간혹 원하지 않은 결과를 불러올 수 있다. 예를 들어 숫자의 비교를 원했는데, 문자열로 캐스팅해서 비교를 한다면 값의 비교가 원하는대로 동작하지 않게 된다. 또한 인덱스를 효과적으로 사용하지 못해, 처리속도가 늦어지는 원인이 되기도 한다. 우리는 SQL에서 지원하는 CAST라는 함수를 이용해서 명시적인 형변환을 할 수 있다.

CAST

CAST 함수는 값과 변환할 타입을 인자로 받아, CAST(expr AS type)와 같이 사용한다.

1
2
3
4
5
6
SELECT CAST('1' AS INTEGER);
-- 결과: 1
SELECT CAST('2022-12-31' AS DATE);
-- 결과: 2022-12-31
SELECT CAST('2022-12-31' AS TIMESTAMP);
-- 결과: 2022-12-31 00:00:00

CONVERT (MySQL)

CONVERT 함수는 MySQL에서만 동작하는 형변환 함수이다. CAST와 마찬가지로 값과 변환할 타입을 인자로 받아, CONVERT(expr, type)와 같이 사용한다.

1
2
3
4
SELECT CONVERT(123, TEXT);
-- 결과: '123'
SELECT CONVERT('2022-12-31', TIMESTAMP);
-- 결과: 2022-12-31 00:00:00

:: Operator (PostgreSQL)

PostgreSQL에서는 operator를 통해서 type변환을 지원하는데, 값::Type을 통해서 캐스팅을 할수 있다. 함수에 비해 사용법이 간편하고 가독성이 좋다는 장점이 있다.

1
2
3
4
SELECT '1000'::INTEGER;
-- 결과: 1000
SELECT '2022-12-31'::TIMESTAMP;
-- 결과: 2022-12-31 00:00:00
This post is licensed under CC BY 4.0 by the author.