데이터 타입 변환
데이터 타입 변환 (Data type conversion)
많은 경우 한 데이터 타입의 값을 다른 데이터 타입으로 변환할 수 있어요. 예를 들어 INTEGER 값을 부동 소수점 데이터 타입 값으로 변환할 수 있죠. 데이터 타입을 변환하는 것을 캐스팅(casting) 이라고 해요. 이 페이지에서는 명시적 캐스팅과 암시적 캐스팅(coercion)의 차이, 우선순위, 그리고 지원되는 변환 표를 다뤄요.
본문
많은 경우 한 데이터 타입의 값을 다른 데이터 타입으로 변환할 수 있어요. 예를 들어 INTEGER 값을 부동 소수점 데이터 타입 값으로 변환할 수 있어요. 데이터 타입을 변환하는 것을 캐스팅(casting) 이라고 해요.
명시적 캐스팅 vs 암시적 캐스팅
사용자는 값을 한 데이터 타입에서 다른 타입으로 명시적으로 변환할 수 있어요. 이를 명시적 캐스팅(explicit casting) 이라고 해요.
어떤 상황에서는 Snowflake가 값을 다른 데이터 타입으로 자동 변환해요. 이를 암시적 캐스팅(implicit casting) 또는 강제(coercion) 라고 해요.
명시적 캐스팅
사용자는 다음 옵션 중 하나를 사용해 값을 명시적으로 캐스트할 수 있어요.
예를 들어 각 쿼리는 문자열 값을 DATE 값으로 캐스트해요.
SELECT CAST('2022-04-01' AS DATE);
SELECT '2022-04-01'::DATE;
SELECT TO_DATE('2022-04-01');
캐스팅은 WHERE 절을 포함해 일반 표현식이 허용되는 대부분의 컨텍스트에서 허용돼요. 예를 들어:
SELECT date_column
FROM log_table
WHERE date_column >= '2022-04-01'::DATE;
암시적 캐스팅 (coercion)
함수(또는 연산자)가 인자(또는 피연산자)와 다르지만 호환되는 데이터 타입을 요구할 때 강제(coercion)가 발생해요.
- 함수 또는 저장 프로시저의 예시:
- 다음 코드는 FLOAT를 기대하는
my_float_function()에 값을 전달할 수 있도록my_integer_column컬럼의 INTEGER 값을 FLOAT로 강제해요.
- 다음 코드는 FLOAT를 기대하는
SELECT my_float_function(my_integer_column)
FROM my_table;
- 연산자의 예시:
- 다음 코드는
||연산자로 값을 연결할 수 있도록 INTEGER 값17을 VARCHAR로 강제해요.
- 다음 코드는
SELECT 17 || '76';
이 SELECT 문의 결과는 문자열 '1776'이에요.
- 다음 문은
<비교 연산자로my_integer_column값을my_float_column값과 비교할 수 있도록my_integer_column컬럼의 INTEGER 값을 FLOAT로 강제해요.
SELECT ...
FROM my_table
WHERE my_integer_column < my_float_column;
모든 컨텍스트 — 예를 들어 모든 연산자 — 가 강제를 지원하는 것은 아니에요.
캐스팅과 우선순위
표현식 안에서 캐스팅할 때, 코드는 표현식의 다른 연산자에 대한 캐스트 연산자의 우선순위를 고려해야 해요.
다음 예제를 고려해요:
SELECT height * width::VARCHAR || ' square meters'
FROM dimensions;
캐스트 연산자는 산술 연산자 *(곱하기)보다 우선순위가 높으므로, 문은 다음 예제처럼 해석돼요.
... height * (width::VARCHAR) ...
표현식 height * width의 결과를 캐스트하려면 다음 예제처럼 괄호를 사용해요.
SELECT (height * width)::VARCHAR || ' square meters'
FROM dimensions;
또 다른 예로, 다음 문을 고려해요:
SELECT -0.0::FLOAT::BOOLEAN;
이것이 다음 예제처럼 해석될 것이라고 예상할 수도 있어요.
SELECT (-0.0::FLOAT)::BOOLEAN;
따라서 FALSE를 반환할 것으로 기대할 거예요 (0 = FALSE, 1 = TRUE).
하지만 캐스트 연산자는 단항 마이너스(negation) 연산자보다 우선순위가 높으므로, 문은 다음 예제처럼 해석돼요.
SELECT -(0.0::FLOAT::BOOLEAN);
따라서 단항 마이너스는 BOOLEAN에 적용할 수 없기 때문에 쿼리 결과는 오류 메시지가 돼요.
캐스트할 수 있는 데이터 타입
다음 표는 Snowflake에서 유효한 데이터 타입 변환을 보여 줘요. 표는 또한 Snowflake가 자동으로 수행할 수 있는 강제(coercion)도 보여 줘요.
Note
내부적으로 CAST 함수와 :: 연산자는 적절한 변환 함수를 호출해요. 예를 들어 NUMBER를 BOOLEAN으로 캐스트하면 Snowflake는 TO_BOOLEAN 함수를 호출해요. 각 변환 함수의 사용 메모는 캐스트로 간접적으로 호출할 때와 함수를 직접 호출할 때 모두 적용돼요. 예를 들어 CAST(my_decimal_column AS BOOLEAN)을 실행하면 DECIMAL 값으로 TO_BOOLEAN을 호출하는 규칙이 적용돼요. 편의를 위해 표에는 관련 변환 함수 링크가 포함돼 있어요.
반구조적 타입과 구조적 타입 사이의 변환에 대한 자세한 내용은 구조적 및 반구조적 타입 변환을 참고해요.
| 소스 데이터 타입 | 대상 데이터 타입 | 캐스트 가능 | 강제 가능 | 변환 함수 | 비고 |
|---|---|---|---|---|---|
| ARRAY | |||||
| VARCHAR | ✔ | ❌ | TO_VARCHAR | 없음. | |
| VARIANT | ✔ | ✔ | TO_VARIANT | 없음. | |
| VECTOR | ✔ | ✔ | 변환에는 명시적 캐스팅을 사용해요. 자세한 내용은 Vector 변환을 참고해요. | ||
| BINARY | |||||
| VARCHAR | ✔ | ❌ | TO_VARCHAR | 없음. | |
| VARIANT | ✔ | ❌ | TO_VARIANT | 없음. | |
| BOOLEAN | |||||
| DECFLOAT | ✔ | ✔ | TO_DECFLOAT | 예: FALSE에서 0으로. |
|
| NUMBER | ✔ | ❌ | TO_NUMBER | 없음. | |
| VARCHAR | ✔ | ✔ | TO_VARCHAR | 예: TRUE에서 'true'로. |
|
| VARIANT | ✔ | ✔ | TO_VARIANT | 없음. | |
| DATE | |||||
| TIMESTAMP | ✔ | ✔ | TO_TIMESTAMP | 없음. | |
| VARCHAR | ✔ | ✔ | TO_VARCHAR | 없음. | |
| VARIANT | ✔ | ❌ | TO_VARIANT | 없음. | |
| DECFLOAT (십진 부동 소수점 숫자) | |||||
| BOOLEAN | ✔ | ✔ | TO_BOOLEAN | 예: 0에서 FALSE로. |
|
| FLOAT | ✔ | ✔ | TO_DOUBLE | 없음. | |
| NUMBER[(p,s)] | ✔ | ✔ | TO_NUMBER | 없음. | |
| VARCHAR | ✔ | ✔ | TO_VARCHAR | 없음. | |
| VARIANT | ✔ | ❌ | TO_VARIANT | 없음. | |
| FLOAT (부동 소수점 숫자) | |||||
| BOOLEAN | ✔ | ✔ | TO_BOOLEAN | 예: 0.0에서 FALSE로. |
|
| DECFLOAT | ✔ | ✔ | TO_DECFLOAT | 없음. | |
| NUMBER[(p,s)] | ✔ | ✔ | TO_NUMBER | 없음. | |
| VARCHAR | ✔ | ✔ | TO_VARCHAR | 없음. | |
| VARIANT | ✔ | ✔ | TO_VARIANT | 없음. | |
| GEOGRAPHY | |||||
| VARIANT | ✔ | ❌ | TO_VARIANT | 없음. | |
| GEOMETRY | |||||
| VARIANT | ✔ | ❌ | TO_VARIANT | 없음. | |
| Interval 데이터 타입 | |||||
| NUMBER[(p,s)] | ✔ | ❌ | TO_NUMBER | 없음. | |
| VARCHAR | ✔ | ✔ | TO_VARCHAR | 없음. | |
| NUMBER[(p,s)] (고정 소수점 숫자, INTEGER 포함) | |||||
| BOOLEAN | ✔ | ✔ | TO_BOOLEAN | 예: 0에서 FALSE로. |
|
| DECFLOAT | ✔ | ✔ | TO_DECFLOAT | 없음. | |
| FLOAT | ✔ | ✔ | TO_DOUBLE | 없음. | |
| Interval 데이터 타입 | ✔ | ❌ | — | 캐스트는 단일 구성 요소를 가진 interval 데이터 타입에만 지원돼요: INTERVAL YEAR, INTERVAL DAY, INTERVAL HOUR, INTERVAL MINUTE, INTERVAL SECOND. | |
| TIMESTAMP | ✔ | ✔ | TO_TIMESTAMP | [1] | |
| VARCHAR | ✔ | ✔ | TO_VARCHAR | 없음. | |
| VARIANT | ✔ | ✔ | TO_VARIANT | 없음. | |
| OBJECT | |||||
| ARRAY | ✔ | ❌ | TO_ARRAY | 없음. | |
| VARCHAR | ✔ | ❌ | TO_VARCHAR | 없음. | |
| VARIANT | ✔ | ✔ | TO_VARIANT | 없음. | |
| PERIOD | |||||
| VARCHAR | ✔ | ❌ | TO_VARCHAR | 명시적 캐스트만. 정규 [begin, end) 형식을 렌더링해요. |
|
| TIME | |||||
| VARCHAR | ✔ | ✔ | TO_VARCHAR | 없음. | |
| VARIANT | ✔ | ❌ | TO_VARIANT | 없음. | |
| TIMESTAMP | |||||
| DATE | ✔ | ✔ | TO_DATE , DATE | 없음. | |
| TIME | ✔ | ✔ | TO_TIME , TIME | 없음. | |
| VARCHAR | ✔ | ✔ | TO_VARCHAR | 없음. | |
| VARIANT | ✔ | ❌ | TO_VARIANT | 없음. | |
| VARCHAR | |||||
| BOOLEAN | ✔ | ✔ | TO_BOOLEAN | 예: 'false'에서 FALSE로. |
|
| DATE | ✔ | ✔ | TO_DATE , DATE | 없음. | |
| DECFLOAT | ✔ | ✔ | TO_DECFLOAT | 없음. | |
| FLOAT | ✔ | ✔ | TO_DOUBLE | 예: '12.34'에서 12.34로. |
|
| Interval 데이터 타입 | ✔ | ✔ | — | VARCHAR 값은 interval 리터럴과 같은 방식으로 파싱돼요. | |
| NUMBER[(p,s)] | ✔ | ✔ | TO_NUMBER | 예: '12.34'에서 12.34로. |
|
| PERIOD | ✔ | ❌ | — | 명시적 캐스트만, 대상 타입은 요소 타입을 포함해야 해요. 예: '[2023-03-25, 2026-07-09)'::PERIOD(DATE). bare ::PERIOD로의 캐스트는 유효하지 않아요. VARCHAR 값은 정규 [begin, end) 형식을 사용해야 해요. INSERT에서 일치하는 문자열 리터럴이 PERIOD 컬럼 타입으로 강제돼요. |
|
| TIME | ✔ | ✔ | TO_TIME , TIME | 없음. | |
| TIMESTAMP | ✔ | ✔ | TO_TIMESTAMP | 없음. | |
| UUID | ✔ | ✔ | TO_UUID | 없음. | |
| VARIANT | ✔ | ❌ | TO_VARIANT | 없음. | |
| UUID | |||||
| VARCHAR | ✔ | ✔ | TO_VARCHAR | 없음. | |
| VARIANT | ✔ | ✔ | TO_VARIANT | 없음. | |
| VARIANT | |||||
| ARRAY | ✔ | ✔ | TO_ARRAY | 없음. | |
| BOOLEAN | ✔ | ✔ | TO_BOOLEAN | 예: 'false'를 포함한 VARIANT에서 FALSE로. |
|
| DATE | ✔ | ✔ | TO_DATE , DATE | 없음. | |
| DECFLOAT | ✔ | ❌ | TO_DECFLOAT | 없음. | |
| FLOAT | ✔ | ✔ | TO_DOUBLE | 없음. | |
| GEOGRAPHY | ✔ | ❌ | TO_GEOGRAPHY | 없음. | |
| NUMBER[(p,s)] | ✔ | ✔ | TO_NUMBER | 없음. | |
| OBJECT | ✔ | ✔ | TO_OBJECT | 없음. | |
| TIME | ✔ | ✔ | TO_TIME , TIME | 없음. | |
| TIMESTAMP | ✔ | ✔ | TO_TIMESTAMP | 없음. | |
| UUID | ✔ | ✔ | TO_UUID | 없음. | |
| VARCHAR | ✔ | ✔ | TO_VARCHAR | 없음. | |
| VECTOR | ✔ | ❌ | VARIANT는 FLOAT 또는 INT 타입의 ARRAY를 포함해야 해요. | ||
| VECTOR | |||||
| ARRAY | ✔ | ✔ | TO_ARRAY | 없음. |
[1] NUMBER는 값이 epoch 시작(1970-01-01 00:00:00) 이후의 초로 취급되므로 TIMESTAMP로 변환할 수 있어요.
Note
나열된 각 데이터 타입(예: FLOAT)에 대해 규칙은 해당 데이터 타입의 모든 별칭에 적용돼요. 예를 들어 FLOAT 규칙은 FLOAT의 별칭인 DOUBLE에도 적용돼요.
사용 메모
달리 명시되지 않는 한, 다음 규칙은 명시적 캐스팅과 암시적 캐스팅 모두에 적용돼요.
- 변환은 소스의 데이터 타입뿐만 아니라 값에도 의존해요; 예를 들어:
- VARCHAR 값
'123'은 숫자 값으로 변환할 수 있지만, VARCHAR 값'xyz'는 숫자 값으로 변환할 수 없어요. - VARIANT 타입의 특정 값을 캐스트할 수 있는지 여부는 VARIANT 내부 데이터의 타입에 따라 달라져요. 예를 들어 VARIANT가 TIME 타입의 값을 포함하면, TIME 값을 TIMESTAMP 값으로 캐스트할 수 없으므로 VARIANT 값을 TIMESTAMP 값으로 캐스트할 수 없어요.
- VARCHAR 값
- Snowflake는 인자를 호환되도록 암시적 변환해요. 예를 들어 입력 표현식 중 하나가 숫자 타입이면 반환 타입도 숫자 타입이에요. 즉
SELECT COALESCE('17', 1);은 먼저 VARCHAR 값'17'을 NUMBER 값17로 변환한 다음 첫 번째 비NULL 값을 반환해요.
변환이 불가능하면 암시적 변환은 실패해요. 예를 들어 SELECT COALESCE('foo', 1);은 VARCHAR 값 'foo'를 NUMBER 값으로 변환할 수 없기 때문에 오류를 반환해요.
같은 타입의 인자를 전달하거나, 필요하면 인자를 명시적으로 변환하는 것을 권장해요.
- 암시적 변환이 숫자가 아닌 값을 숫자 값으로 변환할 때, 결과는 NUMBER(18,5) 타입의 값이에요.
상수가 아닌 숫자 문자열 인자의 경우, NUMBER(18,5)가 숫자 값을 표현하기에 충분하지 않으면 값을 표현할 수 있는 타입으로 인자를 캐스트해요.
- 일부 데이터 타입 쌍의 경우 변환으로 정밀도가 손실될 수 있어요; 예를 들어:
- FLOAT 값을 INTEGER 값으로 변환하면 값이 반올림돼요.
- 고정 소수점 숫자(예: NUMBER(38, 0))에서 부동 소수점(예: FLOAT)으로 값을 변환하면, 고정 소수점 숫자를 부동 소수점 숫자에서 정확히 표현할 수 없을 때 반올림이나 절삭이 발생할 수 있어요.
- TIMESTAMP 값을 DATE 값으로 변환하면 시간 정보가 제거돼요.
- Snowflake는 정밀도 손실이 발생할 수 있는 일부 상황에서 값을 변환하지만, 정밀도 손실이 발생할 다른 상황에서는 변환을 허용하지 않아요. 예를 들어 Snowflake는 변환이 다음 상황을 유발할 때 변환을 허용하지 않아요.
- VARCHAR 값을 절삭하는 경우. 예를 들어 Snowflake는 VARCHAR(10)을 VARCHAR(5)로 암시적·명시적으로 캐스트하지 않아요.
- 최하위 자릿수 외의 자릿수 손실을 초래하는 경우. 예를 들어 다음 자릿수 손실은 실패해요.
SELECT 12.3::FLOAT::NUMBER(3,2);
이 예제에서 숫자 12.3은 소수점 앞에 두 자리가 있지만, NUMBER(3,2) 데이터 타입은 소수점 앞에 한 자리만 공간이 있어요.
- 덜 정밀한 타입에서 더 정밀한 타입으로 변환할 때, 변환은 기본값을 사용해요. 예를 들어 DATE 값을 TIMESTAMP_NTZ 값으로 변환하면 시, 분, 초, 소수 초가
0으로 설정돼요. - FLOAT 값을 VARCHAR 값으로 캐스트하면 끝의 0(trailing zeros)이 생략돼요.
예를 들어 다음 문은 VARCHAR 값, FLOAT 값, VARIANT 값을 포함한 행이 있는 테이블을 만들어요. VARIANT 값은 끝의 0으로 표현된 부동 소수점 값을 포함하는 JSON으로 구성돼요.
CREATE OR REPLACE TABLE convert_test_zeros (
varchar1 VARCHAR,
float1 FLOAT,
variant1 VARIANT);
INSERT INTO convert_test_zeros SELECT
'5.000',
5.000,
PARSE_JSON('{"Loan Number": 5.000}');
다음 SELECT 문은 FLOAT 컬럼과 VARIANT 컬럼 안의 FLOAT 값을 모두 명시적으로 VARCHAR로 캐스트해요. 각각의 경우 VARCHAR에는 끝의 0이 없어요.
SELECT varchar1,
float1::VARCHAR,
variant1:"Loan Number"::VARCHAR
FROM convert_test_zeros;
+----------+-----------------+---------------------------------+
| VARCHAR1 | FLOAT1::VARCHAR | VARIANT1:"LOAN NUMBER"::VARCHAR |
|----------+-----------------+---------------------------------|
| 5.000 | 5 | 5 |
+----------+-----------------+---------------------------------+
- 일부 연산은 조건 표현식에 따라 다른 데이터 타입을 반환할 수 있어요. 예를 들어 다음 IFNULL 호출은 입력 값에 따라 약간 다른 데이터 타입을 반환해요.
SELECT SYSTEM$TYPEOF(IFNULL(12.3, 0)),
SYSTEM$TYPEOF(IFNULL(NULL, 0));
+--------------------------------+--------------------------------+
| SYSTEM$TYPEOF(IFNULL(12.3, 0)) | SYSTEM$TYPEOF(IFNULL(NULL, 0)) |
|--------------------------------+--------------------------------|
| NUMBER(3,1)[SB1] | NUMBER(1,0)[SB1] |
+--------------------------------+--------------------------------+
표현식이 둘 이상의 가능한 데이터 타입을 가지면, Snowflake는 실제 결과에 따라 데이터 타입을 선택해요. 계산에서 정밀도와 스케일에 대한 자세한 내용은 산술 연산에서의 스케일과 정밀도를 참고해요. 쿼리가 둘 이상의 결과(예: 여러 행의 결과)를 생성하면 Snowflake는 각 개별 결과를 담을 수 있는 데이터 타입을 선택해요.
- SnowSQL 같은 일부 애플리케이션과 Snowsight 같은 일부 그래픽 사용자 인터페이스는 데이터를 표시할 때 자체 변환·포맷 규칙을 적용해요. 예를 들어 SnowSQL은 BINARY 값을 16진수 숫자만 포함하는 문자열로 표시해요; 이 문자열은 변환 함수를 암시적으로 호출해 생성된 거예요. 따라서 SnowSQL이 표시하는 데이터는 Snowflake가 어떤 데이터 변환을 수행했는지 명확하게 나타내지 못할 수 있어요.
더 알아보기 (Learn more)
- 숫자 데이터 타입 — 숫자형 타입
- 날짜·시간 데이터 타입 — 날짜와 시간 타입
- 논리 데이터 타입 — BOOLEAN 타입
- CAST 함수 — 캐스트 함수