SQL 언어 표현식
SQL 언어 표현식
SQLite는 표준 SQL 언어의 대부분을 이해합니다. 하지만 일부 기능은 생략하고 자체 확장 기능을 추가하기도 합니다. 이 문서는 SQLite에서 사용하는 표현식 구문의 세부 사항을 설명합니다.
출처: 문서
본문
1. 구문
expr:
literal-value bind-parameter schema-name . table-name . column-name unary-operator expr expr binary-operator expr function-name ( function-arguments ) filter-clause over-clause ( expr ) , CAST ( expr AS type-name ) expr COLLATE collation-name expr NOT LIKE GLOB REGEXP MATCH expr expr ESCAPE expr expr ISNULL NOTNULL NOT NULL expr IS NOT DISTINCT FROM expr expr NOT BETWEEN expr AND expr expr NOT IN ( select-stmt ) expr , schema-name . table-function ( expr ) table-name , NOT EXISTS ( select-stmt ) CASE expr WHEN expr THEN expr ELSE expr END raise-function
filter-clause:
FILTER ( WHERE expr )
function-arguments:
DISTINCT expr , * ORDER BY ordering-term ,
ordering-term:
expr COLLATE collation-name DESC ASC NULLS FIRST NULLS LAST
literal-value:
CURRENT_TIMESTAMP numeric-literal string-literal blob-literal NULL TRUE FALSE CURRENT_TIME CURRENT_DATE
over-clause:
OVER window-name ( base-window-name PARTITION BY expr , ORDER BY ordering-term , frame-spec )
frame-spec:
GROUPS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING RANGE ROWS UNBOUNDED PRECEDING expr PRECEDING CURRENT ROW expr PRECEDING CURRENT ROW expr FOLLOWING expr PRECEDING CURRENT ROW expr FOLLOWING EXCLUDE CURRENT ROW EXCLUDE GROUP EXCLUDE TIES EXCLUDE NO OTHERS
ordering-term:
expr COLLATE collation-name DESC ASC NULLS FIRST NULLS LAST
raise-function:
RAISE ( ROLLBACK , expr ) IGNORE ABORT FAIL
select-stmt:
WITH RECURSIVE common-table-expression , SELECT DISTINCT result-column , ALL FROM table-or-subquery join-clause , WHERE expr GROUP BY expr HAVING expr , WINDOW window-name AS window-defn , VALUES ( expr ) , , compound-operator select-core ORDER BY LIMIT expr ordering-term , OFFSET expr , expr
common-table-expression:
table-name ( column-name ) AS NOT MATERIALIZED ( select-stmt ) ,
compound-operator:
UNION UNION INTERSECT EXCEPT ALL
join-clause:
table-or-subquery join-operator table-or-subquery join-constraint
join-constraint:
USING ( column-name ) , ON expr
join-operator:
NATURAL LEFT OUTER JOIN , RIGHT FULL INNER CROSS
ordering-term:
expr COLLATE collation-name DESC ASC NULLS FIRST NULLS LAST
result-column:
expr AS column-alias * table-name . *
table-or-subquery:
schema-name . table-name AS table-alias INDEXED BY index-name NOT INDEXED table-function-name ( expr ) , AS table-alias ( select-stmt ) ( table-or-subquery ) , join-clause
window-defn:
( base-window-name PARTITION BY expr , ORDER BY ordering-term , frame-spec )
frame-spec:
GROUPS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING RANGE ROWS UNBOUNDED PRECEDING expr PRECEDING CURRENT ROW expr PRECEDING CURRENT ROW expr FOLLOWING expr PRECEDING CURRENT ROW expr FOLLOWING EXCLUDE CURRENT ROW EXCLUDE GROUP EXCLUDE TIES EXCLUDE NO OTHERS
type-name:
name ( signed-number , signed-number ) ( signed-number )
signed-number:
+ numeric-literal -
2. 연산자와 구문 분석에 영향을 주는 속성
SQLite는 다음 연산자를 인식해요. 우선순위1 순서(위에서 아래로 / 높은 순에서 낮은 순)로 나열했어요.
| 연산자 2 |
|---|
| ~ [expr] + [expr] - [expr] |
| [expr] COLLATE (collation-name) 3 |
| || -> ->> |
| * / % |
| + - |
| & | << >> |
| [expr] ESCAPE [escape-character-expr] 4 |
| < > <= >= |
| = == <> != IS IS NOT IS DISTINCT FROM IS NOT DISTINCT FROM [expr] BETWEEN5 [expr] AND [expr] IN5 MATCH5 LIKE5 REGEXP5 GLOB5 [expr] ISNULL [expr] NOTNULL [expr] NOT NULL |
| NOT [expr] |
| AND |
| OR |
- 같은 표 셀 안에 표시된 연산자들은 우선순위가 같아요.
[expr]은 이항 연산자가 아닌 연산자의 피연산자 위치를 나타내요.[expr]이 붙지 않은 연산자는 이항 연산자이고 왼쪽 결합(left-associative)이에요.COLLATE절(콜레이션 이름 포함)은 단일 후위 연산자처럼 동작해요.ESCAPE절(이스케이프 문자 포함)은 단일 후위 연산자처럼 동작해요. 앞에 오는[expr] LIKE [expr]표현식에만 결합할 수 있어요.(BETWEEN IN GLOB LIKE MATCH REGEXP)안의 각 키워드에는NOT이 접두될 수 있으며, 이때도 원래 연산자의 우선순위와 결합성을 유지해요.
COLLATE 연산자는 표현식에 콜레이션 순서를 지정하는 단항 후위 연산자예요. COLLATE 연산자가 설정한 콜레이션 순서는 테이블 열 정의의 COLLATE 절로 결정된 콜레이션 순서를 덮어써요. 자세한 내용은 Datatype In SQLite3 문서의 콜레이션 순서 논의를 참고하세요.
단항 연산자 **+는 아무 일도 하지 않아요. 문자열, 숫자, BLOB, NULL에 적용할 수 있고, 항상 피연산자와 같은 값을 반환해요.
등호와 부등호 연산자에는 두 가지 변형이 있어요. 같음은 **= 또는 **==를 쓸 수 있고, 같지 않음은 **!= 또는 **<>를 쓸 수 있어요. **|| 연산자는 '연결(concatenate)' 연산자로, 두 피연산자의 문자열을 이어 붙여요. **-> 및 **->> 연산자는 '추출(extract)' 연산자로, 왼쪽 항(LHS)에서 오른쪽 항(RHS) 구성 요소를 추출해요. 예제는 JSON 하위 구성 요소 추출을 참고하세요.
**% 연산자는 두 피연산자를 INTEGER 유형으로 캐스팅한 다음, 왼쪽 정수를 오른쪽 정수로 나눈 나머지를 계산해요. 다른 산술 연산자들은 두 피연산자가 모두 정수이고 오버플로가 발생하지 않으면 정수 연산을 수행하고, 어느 한쪽이 실수이거나 정수 연산에서 오버플로가 발생하면 IEEE Standard 754에 따라 부동 소수점 연산을 수행해요. 정수 나눗셈은 0 방향으로 잘린 정수 결과를 만들어요.
모든 이항 연산자의 결과는 숫자 값 또는 NULL이에요. 단, **|| 연결 연산자와 **-> 및 **->> 추출 연산자는 어떤 유형의 값도 반환할 수 있어요.
모든 연산자는 일반적으로 피연산자 중 하나라도 NULL이면 NULL로 평가돼요. 단, 아래 명시된 특정 예외가 있어요. 이는 SQL92 표준을 따르는 거예요.
NULL과 함께 사용될 때: **AND는 다른 피연산자가 false이면 0(false)으로 평가되고, **OR은 다른 피연산자가 true이면 1(true)로 평가돼요.
**IS 및 **IS NOT 연산자는 피연산자 중 하나 또는 둘 다 NULL인 경우를 제외하면 **= 및 **!=처럼 동작해요. 이 경우, 두 피연산자가 모두 NULL이면 IS 연산자는 1(true)로 평가되고 IS NOT 연산자는 0(false)으로 평가돼요. 한 피연산자가 NULL이고 다른 하나는 NULL이 아니면 IS 연산자는 0(false)으로 평가되고 IS NOT 연산자는 1(true)이에요. IS 또는 IS NOT 표현식이 NULL로 평가되는 것은 불가능해요.
**IS NOT DISTINCT FROM 연산자는 **IS 연산자의 다른 표기법이에요. 마찬가지로 **IS DISTINCT FROM 연산자는 **IS NOT과 같은 뜻이에요. 표준 SQL은 간결한 IS 및 IS NOT 표기를 지원하지 않아요. 그 간결한 형태는 SQLite 확장 기능이에요. 대부분의 다른 SQL 데이터베이스 엔진에서는 가독성이 떨어지는 IS NOT DISTINCT FROM 및 IS DISTINCT FROM 연산자를 사용해야 해요.
3. 리터럴 값(상수)
리터럴 값은 상수를 나타내요. 리터럴 값은 정수, 부동 소수점 숫자, 문자열, BLOB 또는 NULL일 수 있어요.
정수 및 부동 소수점 리터럴(통칭 '숫자 리터럴')의 구문은 다음 다이어그램과 같아요.
numeric-literal:
digit _ . E e digit _ . digit _ - digit _ + 0x 0X hexdigit _
숫자 리터럴에 소수점이나 지수 절이 있거나 -9223372036854775808보다 작거나 9223372036854775807보다 크면 부동 소수점 리터럴이에요. 그렇지 않으면 정수 리터럴이에요. 부동 소수점 리터럴의 지수 절을 시작하는 E 문자는 대문자나 소문자 모두 사용할 수 있어요. . 문자는 항상 소수점으로 사용돼요. 로케일 설정에서 이 역할에 ,를 지정하더라도 마찬가지예요. 소수점에 ,를 사용하면 구문상 모호함이 생기기 때문이에요.
SQLite 버전 3.46.0(2024-05-23)부터 임의의 두 숫자 사이에 밑줄(_) 문자를 하나 더 추가할 수 있어요. 밑줄은 사람이 읽기 쉽도록 하기 위한 것일 뿐이며 SQLite는 이를 무시해요.
16진수 정수 리터럴은 C 언어 표기법을 따르며, 0x 또는 0X 뒤에 16진수 숫자가 와요. 예를 들어 0x1234는 4660과 같고 0x8000000000000000은 -9223372036854775808과 같아요. 16진수 정수 리터럴은 64비트 2의 보수 정수로 해석되므로 정밀도는 유효 숫자 16자리로 제한돼요. 16진수 정수 지원은 SQLite 버전 3.8.6(2014-08-15)에 추가됐어요.
하위 호환성을 위해 0x 16진수 정수 표기법은 SQL 언어 파서에서만 이해하고, 유형 변환 루틴에서는 이해하지 않아요. 16진수 정수 형식의 텍스트를 포함하는 문자열 변수는 CAST 표현식으로 인한 형 변환, 열 선호도(column affinity) 변환, 숫자 연산 수행 전, 또는 기타 런타임 변환에서 정수로 강제 변환할 때 16진수 정수로 해석되지 않아요. 16진수 정수 형식의 문자열 값을 정수 값으로 강제 변환할 때, 변환 과정은 x 문자를 만나면 멈추기 때문에 결과 정수 값은 항상 0이에요. SQLite는 16진수 정수 표기법이 SQL 문 텍스트에 나타날 때만 이해하며, 데이터베이스 콘텐츠의 일부로 나타날 때는 이해하지 못해요.
문자열 상수는 문자열을 작은따옴표(')로 감싸서 만들어요. 문자열 안의 작은따옴표는 Pascal에서처럼 작은따옴표 두 개를 연속으로 넣어 표현할 수 있어요. 백슬래시를 사용하는 C 스타일 이스케이프는 표준 SQL이 아니므로 지원하지 않아요.
BLOB 리터럴은 16진수 데이터를 포함하는 문자열 리터럴이며 앞에 x 또는 X 문자가 하나 붙어요. 예: X'53514C697465'
리터럴 값은 NULL 토큰일 수도 있어요.
4. 매개변수
'variable' 또는 'parameter' 토큰은 sqlite3_bind() 계열의 C/C++ 인터페이스를 사용하여 런타임에 채워지는 값의 자리표시자를 표현식에 지정합니다. 매개변수는 여러 형태를 취할 수 있습니다:
| 형식 | 설명 |
|---|---|
| **?**NNN | 물음표 뒤에 숫자 NNN이 오면 NNN 번째 매개변수의 자리를 나타냅니다. NNN은 1 이상이고 SQLITE_MAX_VARIABLE_NUMBER 이하여야 합니다. |
| ? | 숫자가 뒤따르지 않는 물음표는 이미 할당된 가장 큰 매개변수 번호보다 1 큰 번호로 매개변수를 만듭니다. 이로 인해 매개변수 번호가 SQLITE_MAX_VARIABLE_NUMBER보다 커지면 오류입니다. 이 매개변수 형식은 다른 데이터베이스 엔진과의 호환을 위해 제공됩니다. 그러나 물음표 개수를 잘못 세기 쉽기 때문에 이 형식의 사용은 권장되지 않습니다. 프로그래머는 아래의 기호 형식이나 위의 ?NNN 형식을 사용하는 것이 좋습니다. |
| **:**AAAA | 콜론 뒤에 식별자 이름이 오면 이름이 :AAAA인 명명된 매개변수의 자리를 나타냅니다. 명명된 매개변수에도 번호가 부여됩니다. 부여되는 번호는 이미 할당된 가장 큰 매개변수 번호보다 1 큽니다. 이로 인해 매개변수 번호가 SQLITE_MAX_VARIABLE_NUMBER보다 커지면 오류입니다. 혼동을 피하기 위해 명명된 매개변수와 번호 매개변수를 섞어 쓰지 않는 것이 가장 좋습니다. |
| **@**AAAA | "at" 기호는 콜론과 완전히 동일하게 동작하지만, 생성되는 매개변수의 이름이 @AAAA라는 점만 다릅니다. |
| **$**AAAA | 달러 기호 뒤에 식별자 이름이 오는 경우에도 이름이 $AAAA인 명명된 매개변수의 자리를 나타냅니다. 이 경우 식별자 이름에는 "::"가 한 번 이상 포함될 수 있고, 공백이 없는 임의의 텍스트를 담은 "(...)"로 둘러싸인 접미사가 포함될 수 있습니다. 이 구문은 Tcl 프로그래밍 언어의 변수 이름 형태입니다. 이 구문이 존재하는 이유는 SQLite가 실제로는 야생으로 탈출한 Tcl 확장이기 때문입니다. |
sqlite3_bind()를 사용하여 값을 할당하지 않은 매개변수는 NULL로 취급됩니다. sqlite3_bind_parameter_index() 인터페이스를 사용하면 기호 매개변수 이름을 이에 해당하는 숫자 인덱스로 변환할 수 있습니다.
최대 매개변수 번호는 컴파일 시점에 SQLITE_MAX_VARIABLE_NUMBER 매크로에 의해 설정됩니다. 개별 데이터베이스 연결 D는 sqlite3_limit(D, SQLITE_LIMIT_VARIABLE_NUMBER,...) 인터페이스를 사용하여 최대 매개변수 번호를 컴파일 시점 최대값보다 낮출 수 있습니다.
5. LIKE, GLOB, REGEXP, MATCH 및 extract 연산자
LIKE 연산자는 패턴 일치 비교를 수행합니다. LIKE 연산자의 오른쪽 피연산자는 패턴을 포함하고 왼쪽 피연산자는 패턴과 대조할 문자열을 포함합니다.
LIKE 패턴에서 퍼센트 기호("%")는 문자열의 0개 이상의 문자 시퀀스와 일치합니다. 밑줄("_")은 문자열의 임의의 한 문자와 일치합니다. 다른 문자는 그 자신 또는 대문자/소문자 동등 문자와 일치합니다(즉, 대소문자를 구분하지 않는 일치).
중요 참고: SQLite는 기본적으로 ASCII 문자에 대해서만 대문자/소문자를 인식합니다. LIKE 연산자는 ASCII 범위를 벗어난 유니코드 문자에 대해서는 기본적으로 대소문자를 구분합니다. 예를 들어, 'a' LIKE 'A' 표현식은 TRUE이지만 **'æ' LIKE 'Æ'**는 FALSE입니다. SQLite의 ICU 확장에는 모든 유니코드 문자에 대해 대소문자 접기를 수행하는 향상된 LIKE 연산자 버전이 포함되어 있습니다.
선택적 ESCAPE 절이 있으면 ESCAPE 키워드 뒤의 표현식은 단일 문자로 구성된 문자열로 계산되어야 합니다. 이 문자는 LIKE 패턴에서 리터럴 퍼센트 또는 밑줄 문자를 포함하는 데 사용할 수 있습니다. 이스케이프 문자 뒤에 퍼센트 기호(%), 밑줄(_), 또는 이스케이프 문자 자체가 또 오면 각각 리터럴 퍼센트 기호, 밑줄, 또는 단일 이스케이프 문자와 일치합니다.
중위 LIKE 연산자는 애플리케이션 정의 SQL 함수 like(Y,X) 또는 like(Y,X,Z)를 호출하여 구현됩니다.
LIKE 연산자는 case_sensitive_like 프래그마를 사용하여 대소문자를 구분하도록 만들 수 있습니다.
GLOB 연산자는 LIKE와 비슷하지만 와일드카드에 Unix 파일 글로빙 구문을 사용합니다. 또한 GLOB는 LIKE와 달리 대소문자를 구분합니다. GLOB와 LIKE 모두 NOT 키워드를 앞에 붙여 검사의 의미를 반전시킬 수 있습니다. 중위 GLOB 연산자는 glob(Y,X) 함수를 호출하여 구현되며 해당 함수를 재정의하여 수정할 수 있습니다.
REGEXP 연산자는 regexp() 사용자 함수의 특수 구문입니다. 기본적으로 정의된 regexp() 사용자 함수가 없으므로 REGEXP 연산자를 사용하면 일반적으로 오류 메시지가 발생합니다. 런타임에 "regexp"라는 애플리케이션 정의 SQL 함수가 추가되면 "X REGEXP Y" 연산자는 "regexp(Y,X)" 호출로 구현됩니다.
MATCH 연산자는 match() 애플리케이션 정의 함수의 특수 구문입니다. 기본 match() 함수 구현은 예외를 발생시키며 실제로는 어떤 용도로도 유용하지 않습니다. 그러나 확장 기능은 match() 함수를 더 유용한 논리로 재정의할 수 있습니다.
extract 연산자는 ->() 및 ->>() 함수의 특수 구문 역할을 합니다. 이 함수들의 기본 구현은 JSON 하위 구성 요소 추출을 수행하지만, 확장 기능은 다른 목적으로 이를 재정의할 수 있습니다.
6. BETWEEN 연산자
BETWEEN 연산자는 논리적으로 두 개의 비교식과 동일합니다. "x BETWEEN y AND z"는 "x**>=y AND x<=**z"와 동일하지만, BETWEEN을 사용하면 x 표현식은 한 번만 평가됩니다.
7. CASE 표현식
CASE 표현식은 다른 프로그래밍 언어의 IF-THEN-ELSE와 유사한 역할을 합니다.
CASE 키워드와 첫 번째 WHEN 키워드 사이에 오는 선택적 표현식을 "기본(base)" 표현식이라고 합니다. CASE 표현식에는 기본 표현식이 있는 형태와 없는 형태의 두 가지 기본 형식이 있습니다.
기본 표현식이 없는 CASE에서는 맨 왼쪽부터 오른쪽으로 각 WHEN 표현식이 평가되고 그 결과가 불리언으로 처리됩니다. CASE 표현식의 결과는 true로 평가되는 첫 번째 WHEN 표현식에 해당하는 THEN 표현식의 평가 결과입니다. 또는 WHEN 표현식 중 어느 것도 true로 평가되지 않으면 ELSE 표현식(있는 경우)의 평가 결과입니다. ELSE 표현식이 없고 WHEN 표현식 중 어느 것도 true가 아니면 전체 결과는 NULL입니다.
NULL 결과는 WHEN 항을 평가할 때 true가 아닌 것으로 간주됩니다.
기본 표현식이 있는 CASE에서는 기본 표현식이 한 번만 평가되고 그 결과가 각 WHEN 표현식의 평가 결과와 왼쪽에서 오른쪽으로 비교됩니다. CASE 표현식의 결과는 비교가 true인 첫 번째 WHEN 표현식에 해당하는 THEN 표현식의 평가 결과입니다. 또는 WHEN 표현식 중 어느 것도 기본 표현식과 같은 값으로 평가되지 않으면 ELSE 표현식(있는 경우)의 평가 결과입니다. ELSE 표현식이 없고 WHEN 표현식 중 어느 것도 기본 표현식과 같은 결과를 내지 않으면 전체 결과는 NULL입니다.
기본 표현식을 WHEN 표현식과 비교할 때, 기본 표현식과 WHEN 표현식이 각각 = 연산자의 왼쪽 및 오른쪽 피연산자인 경우와 동일한 데이터 정렬 순서, 선호도, NULL 처리 규칙이 적용됩니다.
기본 표현식이 NULL이면 CASE의 결과는 항상 ELSE 표현식이 있을 경우 그 평가 결과이고, 없으면 NULL입니다.
CASE 표현식의 두 형태 모두 지연(lazy) 또는 단락(short-circuit) 평가를 사용합니다.
다음 두 CASE 표현식의 유일한 차이점은 첫 번째 예에서 x 표현식이 정확히 한 번만 평가되지만 두 번째 예에서는 여러 번 평가될 수 있다는 것입니다.
CASE x WHEN w1 THEN r1 WHEN w2 THEN r2 ELSE r3 END
CASE WHEN x=w1 THEN r1 WHEN x=w2 THEN r2 ELSE r3 END
내장 iif(x,y,z) SQL 함수는 논리적으로 "CASE WHEN x THEN y ELSE z END"와 동일합니다. iif() 함수는 SQL Server에 있으며 호환성을 위해 SQLite에 포함되어 있습니다. 일부 개발자는 iif() 함수가 더 간결하기 때문에 선호합니다.
8. IN 및 NOT IN 연산자
IN 및 NOT IN 연산자는 왼쪽에 표현식을 취하고 오른쪽에 값 목록 또는 하위 쿼리를 취합니다. IN 또는 NOT IN 연산자의 오른쪽 피연산자가 하위 쿼리인 경우, 하위 쿼리는 왼쪽 피연산자의 행 값에 있는 열 수와 동일한 수의 열을 가져야 합니다. IN 또는 NOT IN 연산자 오른쪽의 하위 쿼리는 왼쪽 표현식이 행 값 표현식이 아닌 경우 스칼라 하위 쿼리여야 합니다. IN 또는 NOT IN 연산자의 오른쪽 피연산자가 값 목록이면 각 값은 스칼라여야 하고 왼쪽 표현식도 스칼라여야 합니다. IN 또는 NOT IN 연산자의 오른쪽은 테이블 name 또는 테이블 값 함수 name일 수 있으며, 이 경우 오른쪽은 "(SELECT * FROM name)" 형태의 하위 쿼리로 이해됩니다. 오른쪽 피연산자가 빈 집합이면 왼쪽 피연산자와 무관하게, 그리고 왼쪽 피연산자가 NULL이더라도 IN의 결과는 false이고 NOT IN의 결과는 true입니다.
IN 또는 NOT IN 연산자의 결과는 다음 행렬에 의해 결정됩니다.
| 왼쪽 피연산자가 NULL | 오른쪽 피연산자에 NULL 포함 | 오른쪽 피연산자가 빈 집합 | 왼쪽 피연산자가 오른쪽 피연산자에 존재 | IN 연산자 결과 | NOT IN 연산자 결과 | | 아니오 | 아니오 | 아니오 | 아니오 | false | true | | 무관 | 아니오 | 예 | 아니오 | false | true | | 아니오 | 무관 | 아니오 | 예 | true | false | | 아니오 | 예 | 아니오 | 아니오 | NULL | NULL | | 예 | 무관 | 아니오 | 무관 | NULL | NULL |
SQLite는 IN 또는 NOT IN 연산자의 오른쪽에 있는 괄호로 묶인 스칼라 값 목록이 빈 목록이어도 허용하지만, 대부분의 다른 SQL 데이터베이스 엔진과 SQL92 표준은 목록에 최소한 하나의 요소가 있어야 합니다.
9. 테이블 컬럼 이름
컬럼 이름은 CREATE TABLE 문에 정의된 이름 중 하나이거나 다음 특수 식별자 중 하나일 수 있어요: "ROWID", "OID", "ROWID". 이 세 가지 특수 식별자는 모든 테이블의 모든 행에 연결된 고유 정수 키(rowid)를 나타내며, 따라서 WITHOUT ROWID 테이블에서는 사용할 수 없어요. 이 특수 식별자들은 CREATE TABLE 문이 같은 이름의 실제 컬럼을 정의하지 않은 경우에만 행 키를 가리켜요. rowid는 일반 컬럼을 사용할 수 있는 모든 곳에서 사용할 수 있어요.
10. EXISTS 연산자 (The EXISTS operator)
EXISTS 연산자는 항상 정수 값 0과 1 중 하나로 평가돼요. EXISTS 연산자의 오른쪽 피연산자로 지정된 SELECT 문을 실행했을 때 하나 이상의 행이 반환된다면 EXISTS 연산자는 1로 평가돼요. SELECT를 실행했을 때 행이 전혀 반환되지 않는다면 EXISTS 연산자는 0으로 평가돼요.
SELECT 문이 반환하는 각 행의 컬럼 수(있는 경우)와 반환되는 특정 값들은 EXISTS 연산자의 결과에 영향을 주지 않아요. 특히, NULL 값을 포함하는 행은 NULL 값을 포함하지 않는 행과 다르게 처리되지 않아요.
11. 서브쿼리 표현식
괄호로 둘러싸인 SELECT 문은 서브쿼리예요. 집계 및 복합 SELECT 쿼리(UNION이나 EXCEPT 같은 키워드를 사용하는 쿼리)를 포함한 모든 유형의 SELECT 문이 스칼라 서브쿼리로 허용돼요. 서브쿼리 표현식의 값은 괄호 안의 SELECT 문 결과의 첫 번째 행이에요. 괄호 안의 SELECT 문이 행을 반환하지 않으면 서브쿼리 표현식의 값은 NULL이에요.
단일 컬럼을 반환하는 서브쿼리는 스칼라 서브쿼리이며 거의 모든 곳에서 사용할 수 있어요. 두 개 이상의 컬럼을 반환하는 서브쿼리는 행 값 서브쿼리이며 비교 연산자의 피연산자 또는 같은 크기의 컬럼 이름 목록을 가진 UPDATE SET 절의 값으로만 사용할 수 있어요.
12. 상관 서브쿼리
스칼라 서브쿼리로 사용되거나 IN, NOT IN 또는 EXISTS 표현식의 오른쪽 피연산자로 사용되는 SELECT 문은 외부 쿼리의 컬럼을 참조할 수 있어요. 이러한 서브쿼리를 상관 서브쿼리(correlated subquery)라고 해요. 상관 서브쿼리는 결과가 필요할 때마다 다시 평가돼요. 비상관 서브쿼리는 한 번만 평가되고 필요에 따라 결과가 재사용돼요.
13. CAST 표현식
"CAST(expr AS type-name)" 형식의 CAST 표현식은 expr의 값을 type-name이 지정하는 다른 저장 클래스로 변환하는 데 사용돼요. CAST 변환은 값에 컬럼 친화도(column affinity)를 적용할 때 일어나는 변환과 유사해요. 다만 CAST 연산자는 변환이 손실을 동반하고 되돌릴 수 없어도 항상 변환을 수행하는 반면, 컬럼 친화도는 변환이 무손실이고 되돌릴 수 있을 때만 값의 데이터 유형을 변경해요.
expr의 값이 NULL이면 CAST 표현식의 결과도 NULL이에요. 그 외에는 type-name에 컬럼 친화도를 결정하는 규칙을 적용하여 결과의 저장 클래스가 결정돼요.
| type-name의 친화도 (Affinity) | 변환 처리 (Conversion Processing) |
|---|---|
| NONE | 친화도가 없는 type-name으로 값을 캐스팅하면 값이 BLOB으로 변환돼요. BLOB으로의 캐스팅은 먼저 값을 데이터베이스 연결의 인코딩으로 TEXT로 캐스팅한 다음, 결과 바이트 시퀀스를 TEXT 대신 BLOB으로 해석하는 방식으로 이루어져요. |
| TEXT | BLOB 값을 TEXT로 캐스팅하려면 BLOB을 구성하는 바이트 시퀀스가 데이터베이스 인코딩을 사용하여 인코딩된 텍스트로 해석돼요. INTEGER 또는 REAL 값을 TEXT로 캐스팅하면 sqlite3_snprintf()를 통한 것처럼 값이 렌더링되지만, 결과 TEXT는 데이터베이스 연결의 인코딩을 사용해요. |
| REAL | BLOB 값을 REAL로 캐스팅할 때 값은 먼저 TEXT로 변환돼요. TEXT 값을 REAL로 캐스팅할 때, TEXT 값에서 실수로 해석될 수 있는 가장 긴 접두어가 추출되고 나머지는 무시돼요. TEXT에서 REAL로 변환할 때 TEXT 값의 앞쪽 공백은 무시돼요. 실수로 해석될 수 있는 접두어가 없으면 변환 결과는 0.0이에요. |
| INTEGER | BLOB 값을 INTEGER로 캐스팅할 때 값은 먼저 TEXT로 변환돼요. TEXT 값을 INTEGER로 캐스팅할 때, TEXT 값에서 정수로 해석될 수 있는 가장 긴 접두어가 추출되고 나머지는 무시돼요. TEXT에서 INTEGER로 변환할 때 TEXT 값의 앞쪽 공백은 무시돼요. 정수로 해석될 수 있는 접두어가 없으면 변환 결과는 0이에요. 접두어 정수가 +9223372036854775807보다 크면 CAST 결과는 정확히 +9223372036854775807이에요. 마찬가지로 접두어 정수가 -9223372036854775808보다 작으면 CAST 결과는 정확히 -9223372036854775808이에요. INTEGER로 캐스팅할 때 텍스트가 지수가 있는 부동 소수점 값처럼 보인다면, 지수는 정수 접두어의 일부가 아니므로 무시돼요. 예를 들어 "CAST('123e+5' AS INTEGER)"는 12300000이 아니라 123이 돼요. CAST 연산자는 십진 정수만 이해해요. 십육진 정수의 변환은 십육진 정수 문자열의 "0x" 접두어에 있는 "x"에서 멈추므로 CAST 결과는 항상 0이에요. REAL 값을 INTEGER로 캐스팅하면 REAL 값과 0 사이에서 REAL 값에 가장 가까운 정수가 돼요. REAL이 가능한 가장 큰 부호 있는 정수(+9223372036854775807)보다 크면 결과는 가능한 가장 큰 부호 있는 정수이고, REAL이 가능한 가장 작은 부호 있는 정수(-9223372036854775808)보다 작으면 결과는 가능한 가장 작은 부호 있는 정수예요. SQLite 버전 3.8.2(2013-12-06) 이전에는 +9223372036854775807.0보다 큰 REAL 값을 정수로 캐스팅하면 가장 작은 음의 정수인 -9223372036854775808이 되었어요. 이 동작은 동일한 캐스트를 수행할 때 x86/x64 하드웨어의 동작을 모방하기 위한 것이었어요. |
| NUMERIC | TEXT 또는 BLOB 값을 NUMERIC으로 캐스팅하면 INTEGER 또는 REAL 결과가 나와요. 입력 텍스트가 정수처럼 보이고(소수점이나 지수가 없고) 값이 64비트 부호 있는 정수에 맞을 만큼 작으면 결과는 INTEGER예요. 입력 텍스트가 부동 소수점처럼 보이고(소수점 및/또는 지수가 있음) 그 텍스트가 IEEE 754 64비트 부동 소수점과 51비트 부호 있는 정수 사이에서 무손실로 왕복 변환될 수 있는 값을 나타내면 결과는 INTEGER예요. (앞 문장에서 51비트 정수를 지정한 이유는 IEEE 754 64비트 부동 소수점의 가수 길이보다 1비트 적어서 텍스트-부동 소수점 변환 작업에 1비트의 여유를 제공하기 때문이에요.) 64비트 부호 있는 정수 범위를 벗어난 값을 나타내는 모든 텍스트 입력은 REAL 결과를 만들어요. REAL 또는 INTEGER 값을 NUMERIC으로 캐스팅하는 것은 아무 작업도 하지 않아요(no-op). 실수 값이 무손실로 정수로 변환될 수 있는 경우에도 마찬가지예요. |
BLOB이 아닌 값을 BLOB으로 캐스팅한 결과와 BLOB 값을 BLOB이 아닌 값으로 캐스팅한 결과는 데이터베이스 인코딩이 UTF-8, UTF-16be, UTF-16le 중 무엇인지에 따라 달라질 수 있어요.
14. 불리언 표현식
SQL 언어에는 표현식이 평가되고 그 결과가 불리언(참 또는 거짓) 값으로 변환되는 여러 맥락이 있어요. 이러한 맥락은 다음과 같아요.
- SELECT, UPDATE 또는 DELETE 문의 WHERE 절
- SELECT 문에서 조인의 ON 또는 USING 절
- SELECT 문의 HAVING 절
- SQL 트리거의 WHEN 절
- 일부 CASE 표현식의 WHEN 절(들)
SQL 표현식의 결과를 불리언 값으로 변환하기 위해 SQLite는 먼저 CAST 표현식과 같은 방식으로 결과를 NUMERIC 값으로 캐스팅해요. 숫자 0 값(정수 0 또는 실수 0.0)은 거짓으로 간주돼요. NULL 값은 여전히 NULL이에요. 그 외의 모든 값은 참으로 간주돼요.
예를 들어 NULL, 0.0, 0, 'english' 및 '0' 값은 모두 거짓으로 간주돼요. 1, 1.0, 0.1, -0.1 및 '1english' 값은 참으로 간주돼요.
SQLite 3.23.0(2018-04-02)부터 SQLite는 "TRUE"와 "FALSE" 식별자가 다른 의미로 이미 사용되지 않는 경우에만 해당 식별자를 불리언 리터럴로 인식해요. TRUE 또는 FALSE라는 이름의 컬럼, 테이블 또는 다른 객체가 이미 존재한다면, 이전 버전과의 호환성을 위해 TRUE와 FALSE 식별자는 불리언 값이 아닌 그 다른 객체들을 가리켜요.
불리언 식별자 TRUE와 FALSE는 보통 각각 정수 값 1과 0의 별칭일 뿐이에요. 그러나 TRUE 또는 FALSE가 IS 연산자의 오른쪽에 나타나면 IS 연산자는 왼쪽 피연산자를 불리언 값으로 평가하고 적절한 답을 반환해요.
15. 함수
SQLite는 많은 단순(simple), 집계(aggregate), 창(window) SQL 함수를 지원합니다. 설명의 편의를 위해 단순 함수는 다시 코어 함수, 날짜-시간 함수, 수학 함수, JSON 함수로 세분화됩니다. 애플리케이션은 sqlite3_create_function() 인터페이스를 사용하여 C/C++로 작성된 새 함수를 추가할 수 있습니다.
위의 주요 표현식 다이어그램은 모든 함수 호출에 단일 구문을 보여줍니다. 그러나 이는 표현식 다이어그램을 단순화하기 위한 것일 뿐입니다. 실제로 각 함수 유형은 아래에 표시된 것처럼 약간 다른 구문을 가집니다. 주요 표현식 다이어그램에 표시된 함수 호출 구문은 여기에 표시된 세 구문의 합집합입니다.
단순 함수 호출(simple-function-invocation):
simple-func ( expr ) , *
집계 함수 호출(aggregate-function-invocation):
aggregate-func ( DISTINCT expr ) filter-clause , * ORDER BY ordering-term ,
창 함수 호출(window-function-invocation):
window-func ( expr ) filter-clause OVER window-name window-defn , *
OVER 절은 창 함수에 필수이며 그 외의 함수에서는 사용할 수 없습니다. DISTINCT 키워드와 ORDER BY 절은 집계 함수에서만 허용됩니다. FILTER 절은 단순 함수에는 나타날 수 없습니다.
두 형태의 함수가 인자 수만 다르다면 단순 함수와 같은 이름의 집계 함수를 갖는 것이 가능합니다. 예를 들어, 인자가 하나인 max() 함수는 집계 함수이고 인자가 두 개 이상인 max() 함수는 단순 함수입니다. 집계 함수는 일반적으로 창 함수로도 사용할 수 있습니다.