리터럴 타입
리터럴 타입 (Literal Types)
DuckDB는 쿼리에서 NULL, 정수, 문자열 리터럴을 표현하기 위한 특수 리터럴 타입을 가져요. 이것들은 고유한 바인딩과 변환 규칙을 가지고 있어요.
출처: 문서
본문
DuckDB 버전 0.10.0 이전에는 정수와 문자열 리터럴이
INTEGER와VARCHAR타입과 동일하게 동작했어요.
NULL 리터럴 (Null Literals)
NULL 리터럴은 NULL 키워드로 표기돼요. NULL 리터럴은 다른 어떤 타입으로도 암시적으로 변환될 수 있어요.
정수 리터럴 (Integer Literals)
정수 리터럴은 하나 이상의 십진 숫자의 연속으로 표기돼요. 런타임에는 INTEGER_LITERAL 타입의 값이 돼요. INTEGER_LITERAL 타입은 값이 들어맞는 어떤 정수 타입으로도 암시적으로 변환될 수 있어요. 예를 들어 정수 리터럴 42는 TINYINT로 암시적으로 변환될 수 있지만, 정수 리터럴 1000은 그럴 수 없어요.
DuckDB는 16진수나 2진수 리터럴을 직접 지원하지 않아요. 하지만 각각
0x또는0b접두사가 있는 16진수 또는 2진수 표기의 문자열(문자열 리터럴)을 정수 타입으로 캐스트할 수 있어요. 예:'0xFF'::INT = 255또는0b101::INT = 5.
기타 숫자 리터럴 (Other Numeric Literals)
정수가 아닌 숫자 리터럴은 숫자의 정수 부분과 소수 부분을 구분하는 마침표 문자(.)를 사용하는 십진 표기로 표기할 수 있어요. 정수 부분이나 소수 부분 중 하나는 생략될 수 있어요.
SELECT 1.5; -- 1.5
SELECT .50; -- 0.5
SELECT 2.; -- 2.0
정수가 아닌 숫자 리터럴은 E 표기법으로도 표기할 수 있어요. E 표기법에서는 정수 또는 십진 리터럴 뒤에 지수 부분이 오는데, 이는 e 또는 E로 표기하고 그 뒤에 지수를 나타내는 리터럴 정수가 따라와요. 지수 부분은 앞의 값을 10의 지수 승으로 곱해야 한다는 것을 나타내요.
SELECT 1e2; -- 100
SELECT 6.02214e23; -- Avogadro's constant
SELECT 1e-10; -- 1 ångström
숫자 리터럴의 밑줄 (Underscores in Numeric Literals)
DuckDB의 SQL 방언은 숫자 리터럴에서 밑줄 문자 _를 선택적 구분자로 사용하는 것을 허용해요. 밑줄 사용 규칙은 다음과 같아요.
- 밑줄은 정수, 십진, 16진수, 2진수 표기에서 허용돼요.
- 밑줄은 리터럴의 첫 번째나 마지막 문자가 될 수 없어요.
- 밑줄은 양쪽에 정수/숫자 부분이 있어야 해요. 즉, 밑줄이 연속으로 여러 개 있을 수 없고, 소수나 지수 직전이나 직후에 나타날 수 없어요.
예시:
SELECT 100_000_000; -- 100000000
SELECT '0xFF_FF'::INTEGER; -- 65535
SELECT 1_2.1_2E0_1; -- 121.2
SELECT '0b0_1_0_1'::INTEGER; -- 5
문자열 리터럴 (String Literals)
문자열 리터럴은 단일 따옴표(', 아포스트로피)로 둘러싸고 STRING_LITERAL 값이 돼요. 큰따옴표(")는 문자열 구분자로 사용할 수 없다는 점을 기억하세요. 큰따옴표는 대신 인용 식별자를 구분하는 데 사용돼요.
암시적 문자열 리터럴 연결 (Implicit String Literal Concatenation)
줄바꿈을 하나 이상 포함하는 공백으로만 구분된 연속적인 단일 따옴표 문자열 리터럴은 암시적으로 연결돼요.
SELECT 'Hello'
' '
'World' AS greeting;
다음과 동일해요.
SELECT 'Hello'
|| ' '
|| 'World' AS greeting;
둘 다 다음 결과를 반환해요.
| greeting |
|---|
| Hello World |
암시적 연결은 리터럴 사이에 줄바꿈이 하나 이상 있을 때만 동작한다는 점을 기억하세요. 줄바꿈 없이 공백으로 구분된 인접한 문자열 리터럴을 사용하면 문법 오류가 발생해요.
SELECT 'Hello' ' ' 'World' AS greeting;
Parser Error:
syntax error at or near "' '"
LINE 1: SELECT 'Hello' ' ' 'World' AS greeting;
^
또한 암시적 연결은 단일 따옴표 문자열 리터럴에서만 동작하고 다른 종류의 문자열 값에서는 동작하지 않아요.
암시적 문자열 변환 (Implicit String Conversion)
STRING_LITERAL 인스턴스는 어떤 다른 타입으로도 암시적으로 변환될 수 있어요.
예를 들어 문자열 리터럴을 날짜와 비교할 수 있어요.
SELECT d > '1992-01-01' AS result
FROM (VALUES (DATE '1992-01-01')) t(d);
| result |
|---|
| false |
하지만 VARCHAR 값을 날짜와 비교할 수는 없어요.
SELECT d > '1992-01-01'::VARCHAR
FROM (VALUES (DATE '1992-01-01')) t(d);
Binder Error:
Cannot compare values of type DATE and type VARCHAR - an explicit cast is required
이스케이프 문자열 리터럴 (Escape String Literals)
문자열 리터럴에서 단일 따옴표(아포스트로피) 문자를 이스케이프하려면 ''를 사용해요. 예를 들어 SELECT '''' AS s는 '를 반환해요.
줄바꿈 문자를 위한 \n 같은 일반적인 이스케이프 시퀀스를 활성화하려면 문자열 리터럴 앞에 e(또는 E)를 붙여요.
SELECT e'Hello\nworld' AS msg;
┌──────────────┐
│ msg │
│ varchar │
├──────────────┤
│ Hello\nworld │
└──────────────┘
지원되는 백슬래시 이스케이프 시퀀스는 다음과 같아요.
| Escape sequence | Name | ASCII code |
|---|---|---|
\b |
backspace | 8 |
\f |
form feed | 12 |
\n |
newline | 10 |
\r |
carriage return | 13 |
\t |
tab | 9 |
달러 인용 문자열 리터럴 (Dollar-Quoted String Literals)
DuckDB는 이중 달러 기호($$)로 둘러싸인 달러 인용 문자열 리터럴을 지원해요.
SELECT $$Hello
world$$ AS msg;
┌──────────────┐
│ msg │
│ varchar │
├──────────────┤
│ Hello\nworld │
└──────────────┘
SELECT $$The price is $9.95$$ AS msg;
| msg |
|---|
| The price is $9.95 |
게다가 이중 달러 기호에 영숫자 태그를 넣으면 문자열 리터럴 안에서 일반 이중 달러 기호를 사용할 수 있어요.
SELECT $tag$ this string can contain newlines,
'single quotes',
"double quotes",
and $$dollar quotes$$ $tag$ AS msg;
┌────────────────────────────────────────────────────────────────────────────────────────────────┐
│ msg │
│ varchar │
├────────────────────────────────────────────────────────────────────────────────────────────────┤
│ this string can contain newlines,\n'single quotes',\n"double quotes",\nand $$dollar quotes$$ │
└────────────────────────────────────────────────────────────────────────────────────────────────┘
암시적 연결은 단일 따옴표 문자열 리터럴에서만 작동하며 달러 인용 문자열에서는 작동하지 않아요.