표현식
표현식 (Expressions)
리터럴, 연산자, CAST, CASE, 서브쿼리를 포함한 SQL 표현식 문법을 정리한 문서예요. 하나씩 짚어보면 SQL 작성 감각이 확 붙을 거예요.
출처: 문서
본문
표현식은 Turso가 평가해서 결과를 만들어 내는 값, 연산자, 함수의 조합이에요. 표현식은 SELECT 컬럼, WHERE 조건, ORDER BY, GROUP BY, HAVING, CHECK 제약, DEFAULT 값 등 많은 SQL 절에 나타나요.
Literals
Numeric Literals
SELECT 42; -- integer literal
SELECT -17; -- negative integer
SELECT 3.14; -- real (floating-point) literal
SELECT 2.5e10; -- scientific notation
SELECT 0xFF; -- hexadecimal integer (255)
String Literals
문자열 리터럴은 작은따옴표로 감싸요. 문자열 안에 작은따옴표를 넣으려면 작은따옴표를 연속 두 개 쓰면 돼요:
SELECT 'hello world'; -- text literal
SELECT 'it''s a test'; -- embedded single quote
SELECT ''; -- empty string
Blob Literals
Blob 리터럴은 x 또는 X가 앞에 붙은 16진수 문자열이에요:
SELECT x'CAFEBABE'; -- blob literal
SELECT X'48454C4C4F'; -- blob literal (case insensitive prefix)
NULL Literal
SELECT NULL; -- null value
Boolean Literals
Turso에는 별도의 boolean 타입이 없어요. 정수 0(거짓)과 1(참)을 사용하세요:
SELECT 1; -- true
SELECT 0; -- false
Operators
Arithmetic Operators
| Operator | Description | Example | Result |
|---|---|---|---|
+ |
덧셈 | 3 + 4 |
7 |
- |
뺄셈 | 10 - 3 |
7 |
* |
곱셈 | 3 * 4 |
12 |
/ |
나눗셈 | 10 / 3 |
3 (정수 나눗셈) |
- (unary) |
부정 | -5 |
-5 |
+ (unary) |
no-op | +5 |
5 |
정수 나눗셈은 0 방향으로 절삭해요. 부동소수점 나눗셈을 하려면 CAST를 쓰거나 1.0을 곱하세요:
SELECT 10 / 3; -- 3 (integer division)
SELECT 10 / 3.0; -- 3.333... (real division)
SELECT CAST(10 AS REAL) / 3; -- 3.333...
Comparison Operators
| Operator | Description | Example |
|---|---|---|
= 또는 == |
같음 | x = 5 |
!= 또는 <> |
같지 않음 | x != 5 |
< |
미만 | x < 5 |
> |
초과 | x > 5 |
<= |
이하 | x <= 5 |
>= |
이상 | x >= 5 |
모든 비교 연산자는 1(참), 0(거짓), NULL(피연산자 중 하나가 NULL이면)을 반환해요.
Logical Operators
| Operator | Description | Example |
|---|---|---|
AND |
논리 AND | x > 0 AND x < 10 |
OR |
논리 OR | x = 1 OR x = 2 |
NOT |
논리 NOT | NOT x = 5 |
Bitwise Operators
| Operator | Description | Example | Result |
|---|---|---|---|
& |
비트 AND | 5 & 3 |
1 |
| |
비트 OR | 5 | 3 |
7 |
~ |
비트 NOT | ~5 |
-6 |
<< |
왼쪽 시프트 | 1 << 4 |
16 |
>> |
오른쪽 시프트 | 16 >> 2 |
4 |
String Concatenation
| Operator | Description | Example | Result |
|---|---|---|---|
|| |
연결 | 'hello' || ' ' || 'world' |
'hello world' |
피연산자 중 하나가 배열이면 ||는 대신 배열 연결을 수행해요. Array Operators를 보세요.
Array Operators
Turso Extension: 배열 연산자는 SQLite에는 없는 Turso 전용 기능이에요.
| Operator | Description | Example | Result |
|---|---|---|---|
@> |
모두 포함 | ARRAY[1,2,3] @> ARRAY[1,2] |
1 |
&& |
겹침 | ARRAY[1,2,3] && ARRAY[3,4,5] |
1 |
|| |
배열 연결 | ARRAY[1,2] || ARRAY[3,4] |
[1,2,3,4] |
=, !=, <, >, <=, >= |
비교 | ARRAY[1,2] < ARRAY[1,3] |
1 |
@> 연산자는 왼쪽 배열이 오른쪽 배열의 모든 요소를 포함하는지 검사해요. && 연산자는 두 배열이 공통 요소를 하나라도 공유하는지 검사하고요. 둘 다 1(참) 또는 0(거짓)을 반환해요.
배열 비교는 왼쪽부터 요소 단위로 이루어져요. 비교한 요소가 모두 같으면 더 짧은 배열이 더 작은 것으로 간주돼요.
SELECT ARRAY[1,2,3] @> ARRAY[1,3]; -- 1 (contains both 1 and 3)
SELECT ARRAY[1,2] && ARRAY[3,4]; -- 0 (no common elements)
SELECT ARRAY[1,2] < ARRAY[1,2,3]; -- 1 (shorter is less)
전체 레퍼런스는 Array Functions를 보세요.
CAST Expression
CAST 표현식은 값을 지정한 타입으로 변환해요.
CAST(expression AS type-name)
| Parameter | Type | Description |
|---|---|---|
| expression | any | 변환할 값 |
| type-name | type | 대상 타입 이름 |
SELECT CAST(3.7 AS INTEGER); -- 3 (truncates toward zero)
SELECT CAST(42 AS TEXT); -- '42'
SELECT CAST('123' AS INTEGER); -- 123
SELECT CAST('abc' AS INTEGER); -- 0
SELECT CAST(NULL AS INTEGER); -- NULL
Turso Extension: 커스텀 타입이 있는 STRICT 테이블에서는 CAST(value AS custom_type)가 커스텀 타입의 ENCODE 함수를 적용해요. 자세한 내용은 CREATE TYPE을 보세요.
COLLATE Expression
COLLATE 표현식은 문자열 비교를 위한 collation sequence를 지정해요.
expression COLLATE collation-name
내장 collation sequence는 다음과 같아요:
| Collation | Description |
|---|---|
BINARY |
바이트 단위 비교 (기본값) |
NOCASE |
ASCII 문자에 대해 대소문자 구분 없는 비교 |
RTRIM |
BINARY와 같지만 끝의 공백은 무시해요 |
SELECT 'ABC' = 'abc'; -- 0 (BINARY comparison)
SELECT 'ABC' = 'abc' COLLATE NOCASE; -- 1 (case-insensitive)
SELECT 'abc ' = 'abc' COLLATE RTRIM; -- 1 (trailing space ignored)
SELECT name FROM users ORDER BY name COLLATE NOCASE;
Pattern Matching
LIKE Operator
LIKE 연산자는 대소문자 구분 없는 패턴 매칭을 수행해요(ASCII 문자 기준). % 와일드카드는 임의의 문자 시퀀스와 일치하고, _는 임의의 한 문자와 일치해요.
expression [NOT] LIKE pattern [ESCAPE escape-char]
SELECT 'Hello World' LIKE 'hello%'; -- 1 (case-insensitive)
SELECT 'Hello World' LIKE 'H_llo%'; -- 1 (_ matches 'e')
SELECT 'Hello World' LIKE '%World'; -- 1
SELECT '10%' LIKE '10\%' ESCAPE '\'; -- 1 (escaped % literal)
GLOB Operator
GLOB 연산자는 Unix 스타일 와일드카드로 대소문자 구분 있는 패턴 매칭을 수행해요. *는 임의의 문자 시퀀스와 일치하고, ?는 임의의 한 문자와 일치해요.
expression [NOT] GLOB pattern
SELECT 'Hello' GLOB 'H*'; -- 1
SELECT 'Hello' GLOB 'h*'; -- 0 (case-sensitive)
SELECT 'Hello' GLOB 'H?llo'; -- 1
SELECT 'Hello' GLOB 'H[a-z]*'; -- 1 (character class)
REGEXP Operator
REGEXP 연산자는 정규 표현식 매칭을 수행해요. regexp 확장이 필요해요(기본으로 로드돼요).
expression [NOT] REGEXP pattern
SELECT 'Hello123' REGEXP '[A-Za-z]+[0-9]+'; -- 1
SELECT '[email protected]' REGEXP '^[^@]+@[^@]+\.[^@]+$'; -- 1
BETWEEN Expression
BETWEEN 표현식은 값이 포함 범위 안에 있는지 검사해요.
expression [NOT] BETWEEN low AND high
BETWEEN 표현식은 expression >= low AND expression <= high와 동일해요:
SELECT 5 BETWEEN 1 AND 10; -- 1
SELECT 5 NOT BETWEEN 1 AND 3; -- 1
SELECT 'b' BETWEEN 'a' AND 'c'; -- 1
IN Expression
IN 표현식은 값이 목록이나 서브쿼리 결과의 어떤 값과 일치하는지 검사해요.
expression [NOT] IN (value1, value2, ...)
expression [NOT] IN (select-statement)
SELECT 3 IN (1, 2, 3, 4, 5); -- 1
SELECT 'red' NOT IN ('blue', 'green'); -- 1
SELECT name FROM users
WHERE id IN (SELECT user_id FROM orders WHERE total > 100);
EXISTS Expression
EXISTS 표현식은 서브쿼리가 최소 한 행을 반환하면 1, 아니면 0을 반환해요.
[NOT] EXISTS (select-statement)
SELECT EXISTS (SELECT 1 FROM users WHERE name = 'Alice'); -- 1 if Alice exists
SELECT name FROM departments d
WHERE EXISTS (
SELECT 1 FROM employees e
WHERE e.department_id = d.id
);
IS NULL / IS NOT NULL
IS NULL 표현식은 값이 NULL인지 검사해요. 항상 NULL을 반환하는 = NULL과 달리, IS NULL은 1 또는 0을 반환해요.
expression IS NULL
expression IS NOT NULL
SELECT NULL IS NULL; -- 1
SELECT NULL = NULL; -- NULL (not 1!)
SELECT 42 IS NOT NULL; -- 1
SELECT NULL IS NOT NULL; -- 0
IS DISTINCT FROM
IS DISTINCT FROM 표현식은 NULL을 비교 가능한 값으로 다루면서 두 값을 비교해요.
expression IS [NOT] DISTINCT FROM expression
SELECT 1 IS DISTINCT FROM 2; -- 1 (different values)
SELECT 1 IS DISTINCT FROM 1; -- 0 (same value)
SELECT NULL IS DISTINCT FROM NULL; -- 0 (both NULL)
SELECT NULL IS DISTINCT FROM 1; -- 1 (NULL vs non-NULL)
SELECT 1 IS NOT DISTINCT FROM 1; -- 1
CASE Expression
CASE 표현식은 SQL 표현식 안에서 조건 로직을 제공해요.
Simple CASE
CASE expression
WHEN value1 THEN result1
WHEN value2 THEN result2
...
[ELSE default_result]
END
Searched CASE
CASE
WHEN condition1 THEN result1
WHEN condition2 THEN result2
...
[ELSE default_result]
END
WHEN 절이 하나도 일치하지 않고 ELSE 절도 없으면 CASE 표현식은 NULL을 반환해요.
-- Simple CASE
SELECT name,
CASE status
WHEN 'A' THEN 'Active'
WHEN 'I' THEN 'Inactive'
ELSE 'Unknown'
END AS status_text
FROM users;
-- Searched CASE
SELECT name, score,
CASE
WHEN score >= 90 THEN 'A'
WHEN score >= 80 THEN 'B'
WHEN score >= 70 THEN 'C'
ELSE 'F'
END AS grade
FROM students;
Scalar Subqueries
괄호로 감싸서 단일 값을 반환하는 서브쿼리는 표현식으로 쓸 수 있어요.
(select-statement)
서브쿼리는 정확히 한 컬럼과 최대 한 행을 반환해야 해요. 서브쿼리가 행을 반환하지 않으면 표현식은 NULL로 평가돼요.
SELECT name,
(SELECT COUNT(*) FROM orders WHERE orders.user_id = users.id) AS order_count
FROM users;
SELECT * FROM products
WHERE price > (SELECT AVG(price) FROM products);
RAISE Function
RAISE 함수는 오류 조건을 발생시켜요. 표준 SQLite에서 RAISE는 트리거 안에서만 쓸 수 있지만, Turso에서는 RAISE(ABORT, msg)를 트리거 밖에서도 쓸 수 있어요 — CHECK 제약, 커스텀 타입 ENCODE 표현식, 독립 실행 쿼리에서요. 다른 형태(RAISE(IGNORE), RAISE(ROLLBACK, msg), RAISE(FAIL, msg))는 트리거 안에서만 유효해요.
RAISE(IGNORE)
RAISE(ROLLBACK, error-message)
RAISE(ABORT, error-message)
RAISE(FAIL, error-message)
| Form | Description |
|---|---|
RAISE(IGNORE) |
현재 트리거 동작을 중단하되 문장은 계속 진행해요 |
RAISE(ROLLBACK, msg) |
문장을 중단하고 현재 트랜잭션을 롤백해요 |
RAISE(ABORT, msg) |
현재 문장을 중단해요; 트랜잭션의 이전 변경은 유지돼요 |
RAISE(FAIL, msg) |
현재 시점에서 현재 문장을 중단해요; 이전 행 변경은 유지돼요 |
-- In a trigger
CREATE TRIGGER validate_age BEFORE INSERT ON users
BEGIN
SELECT CASE
WHEN NEW.age < 0 THEN RAISE(ABORT, 'age must be non-negative')
END;
END;
-- In a custom type ENCODE expression
CREATE TYPE positive_int BASE integer
ENCODE CASE WHEN value > 0 THEN value
ELSE RAISE(ABORT, 'value must be positive') END
DECODE value;
Operator Precedence
연산자는 다음 순서로 평가돼요(우선순위가 높은 것부터):
| Precedence | Operators |
|---|---|
| 1 (highest) | ~ (unary NOT), + (unary), - (unary) |
| 2 | || (concatenation) |
| 3 | *, / |
| 4 | +, - |
| 5 | <<, >>, &, | |
| 6 | <, <=, >, >=, @>, && |
| 7 | =, ==, !=, <>, IS, IS NOT, IS DISTINCT FROM, IN, LIKE, GLOB, REGEXP, BETWEEN |
| 8 | NOT |
| 9 | AND |
| 10 (lowest) | OR |
필요하면 괄호로 우선순위를 바꿀 수 있어요:
SELECT 2 + 3 * 4; -- 14 (multiplication first)
SELECT (2 + 3) * 4; -- 20 (parentheses override)
See Also
- Data Types — 스토리지 클래스와 타입 어피니티
- Scalar Functions — 표현식에서 쓸 수 있는 내장 함수
- SELECT — 쿼리에서 표현식 사용하기
더 알아보기 (Learn more)
- 데이터 타입 — 스토리지 클래스와 타입 어피니티
- SQLite 호환성 — SQLite와의 차이와 확장 기능
- 실험적 기능 — 배열 연산자 등 활성화 방법
- 집계 함수 — 표현식과 함께 쓰는 집계 함수