SQL 语言表达式

1.语法

表达式:

literal-value bind-parameter schema-name . table-name . column-name unary-operator expr expr binary-operator expr function-name ( DISTINCT expr ) 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

过滤器子句:

字面值:

过度条款:

提升功能:

选择stmt:

类型名称:

2.运算符和影响解析的属性

SQLite 理解这些运算符,按优先顺序1列出
(从上到下/从高到低):

Operators 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

  1. 同一表格单元格中显示的运算符共享优先级。
  2. [expr] ”表示非二元运算符的操作数位置。
      没有“[expr]”附加语的运算符是二元运算符和左结合运算符。
  3. COLLATE 子句(及其排序规则名称)充当单个后缀运算符。
  4. ESCAPE 子句(及其转义字符)充当单个后缀运算符。
      它只能绑定到前面的 [expr] LIKE [expr] 表达式。
  5. (BETWEEN IN GLOB LIKE MATCH REGEXP) 中的每个关键字都可以以
      NOT 为前缀,保留裸运算符的优先级和关联性。

COLLATE 运算符是一元后缀运算符,它将整理序列分配给表达式。COLLATE 运算符设置的整理顺序覆盖表 列定义中的 COLLATE 子句确定的整理顺序。有关更多信息,请参阅SQLite3 中的数据类型文档中 关于整理序列的详细讨论。

一元运算符+是空操作。它可以应用于字符串、数字、blob 或 NULL,并且它始终返回与操作数具有相同值的结果。

请注意,等于和不等于运算符有两种变体。等于可以是 ===不等于运算符可以是 !=<>|| _ 运算符是“连接” - 它将其操作数的两个字符串连接在一起。- >->>运算符是“提取”;他们从 LHS 中提取 RHS 组件。有关示例,请参阅 JSON 子组件提取

%运算符两个操作数都转换为 INTEGER 类型,然后计算左整数除以右整数后的余数。如果两个操作数都是整数并且不会导致溢出,则其他算术运算符执行整数算术,或者根据 IEEE 标准 754,如果任一操作数是实数值或整数算术会产生溢出,则执行浮点算术。整数除法产生一个整数结果,向零截断。

除||外,任何二元运算符的结果都是数值或 NULL 连接运算符,以及->->>提取运算符,它们的计算结果为 NULL 或文本值。

当任何操作数为 NULL 时,所有运算符的计算结果通常为 NULL,具体例外如下所述。这符合 SQL92 标准。

与 NULL 配对时:当另一个操作数为假时,
  AND的计算结果为 0(假);当另一个操作数为真时,
  OR的计算结果为 1(真)。

ISIS NOT运算符的工作方式类似于=!= ,除非其中一个或两个操作数为 NULL。在这种情况下,如果两个操作数均为 NULL,则 IS 运算符的计算结果为 1(真),IS NOT 运算符的计算结果为 0(假)。如果一个操作数为 NULL 而另一个不是,则 IS 运算符的计算结果为 0(假),IS NOT 运算符的计算结果为 1(真)。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。

下图显示了整数和浮点文字(统称为“数字文字”)的语法:

数字文字:

digit . E e digit . digit - digit + 0x hexdigit

如果数字文字有小数点或求幂子句,或者如果它小于 -9223372036854775808 或大于 9223372036854775807,则它是浮点文字。否则它是一个整数文字。浮点文字取幂子句开头的“E”字符可以是大写或小写。这 ”。” 字符始终用作小数点,即使区域设置为此角色指定了“,”——使用“,”作为小数点会导致句法歧义。

十六进制整数文字遵循 C 语言表示法“0x”或“0X”,后跟十六进制数字。例如,0x1234 表示与 4660 相同,0x8000000000000000 表示与 -9223372036854775808 相同。十六进制整数文字被解释为 64 位二进制补码整数,因此精度限制为十六位有效数字。SQLite 版本 3.8.6 (2014-08-15) 添加了对十六进制整数的支持。为了向后兼容,“0x”十六进制整数表示法只能被 SQL 语言解析器理解,而不能被类型转换例程理解。 转换或执行数字操作之前或任何其他运行时转换。将十六进制整数格式的字符串值强制转换为整数值时,转换过程会在看到“x”字符时停止,因此生成的整数值始终为零。SQLite 只理解出现在 SQL 语句文本中的十六进制整数表示法,而不是当它作为数据库内容的一部分出现时。

字符串常量是通过将字符串括在单引号 (') 中形成的。字符串中的单引号可以通过在一行中放置两个单引号来编码——就像在 Pascal 中一样。不支持使用反斜杠字符的 C 风格转义,因为它们不是标准 SQL。

BLOB 文字是包含十六进制数据并以单个“x”或“X”字符开头的字符串文字。示例:X'53514C697465'

文字值也可以是标记“NULL”。

、参数

“变量”或“参数”标记指定表达式中的占位符,用于在运行时使用 C/C++ 接口的sqlite3_bind()系列填充的值。参数可以采用多种形式:

?NNN A question mark followed by a number NNN holds a spot for the NNN-th parameter. NNN must be between 1 and SQLITE_MAX_VARIABLE_NUMBER.
? A question mark that is not followed by a number creates a parameter with a number one greater than the largest parameter number already assigned. If this means the parameter number is greater than SQLITE_MAX_VARIABLE_NUMBER, it is an error. This parameter format is provided for compatibility with other database engines. But because it is easy to miscount the question marks, the use of this parameter format is discouraged. Programmers are encouraged to use one of the symbolic formats below or the ?NNN format above instead.
:AAAA A colon followed by an identifier name holds a spot for a named parameter with the name :AAAA. Named parameters are also numbered. The number assigned is one greater than the largest parameter number already assigned. If this means the parameter would be assigned a number greater than SQLITE_MAX_VARIABLE_NUMBER, it is an error. To avoid confusion, it is best to avoid mixing named and numbered parameters.
@AAAA An "at" sign works exactly like a colon, except that the name of the parameter created is @AAAA.
$AAAA A dollar-sign followed by an identifier name also holds a spot for a named parameter with the name $AAAA. The identifier name in this case can include one or more occurrences of "::" and a suffix enclosed in "(...)" containing any text at all. This syntax is the form of a variable name in the Tcl programming language. The presence of this syntax results from the fact that SQLite is really a Tcl extension that has escaped into the wild.

未使用sqlite3_bind()分配值的 参数被视为 NULL。sqlite3_bind_parameter_index()接口可用于将符号参数名称转换为其等效的数字索引

最大参数数在编译时由SQLITE_MAX_VARIABLE_NUMBER宏设置。单个数据库连接D 可以使用sqlite3_limit (D, SQLITE_LIMIT_VARIABLE_NUMBER ,...) 接口 将其最大参数数减少到编译时最大值以下。

5. LIKE、GLOB、REGEXP、MATCH 和提取运算符

LIKE 运算符进行模式匹配比较。LIKE 运算符右侧的操作数包含模式,左侧操作数包含要与模式匹配的字符串。LIKE 模式中的百分号(“%”)匹配字符串中零个或多个字符的任意序列。LIKE 模式中的下划线(“_”)匹配字符串中的任何单个字符。任何其他字符匹配自身或其小写/大写等效项(即不区分大小写的匹配)。 重要说明:默认情况下,SQLite 仅理解 ASCII 字符的大写/小写。对于超出 ASCII 范围的 unicode 字符,LIKE 运算符默认区分大小写。例如,表达式'a' LIKE 'A' 为 TRUE 但'æ'是假的。SQLite 的 ICU 扩展包括 LIKE 运算符的增强版本,它可以对所有 unicode 字符进行大小写折叠。

如果存在可选的 ESCAPE 子句,则 ESCAPE 关键字后面的表达式的计算结果必须为由单个字符组成的字符串。该字符可以用在 LIKE 模式中以包括文字百分号或下划线字符。后跟百分号 (%)、下划线 (_) 或转义字符本身的第二个实例的转义字符分别与文字百分号、下划线或单个转义字符匹配。

中缀 LIKE 运算符是通过调用应用程序定义的 SQL 函数like( Y , X )like( Y , X , Z )来实现的。

可以使用case_sensitive_like pragma使 LIKE 运算符区分大小写

GLOB 运算符与 LIKE 类似,但其通配符使用 Unix 文件通配符语法。此外,与 LIKE 不同,GLOB 区分大小写。GLOB 和 LIKE 都可以在 NOT 关键字之前以反转测试的意义。中缀 GLOB 运算符是通过调用函数 glob( Y , X )实现的,并且可以通过覆盖该函数进行修改。

REGEXP 运算符是 regexp() 用户函数的特殊语法。默认情况下没有定义 regexp() 用户函数,因此使用 REGEXP 运算符通常会导致出现错误消息。如果在运行时添加名为“regexp”的应用程序定义的 SQL 函数,则“ X REGEXP Y ”运算符将作为对“regexp( Y , X )”的调用来实现。

MATCH 运算符是 match() 应用程序定义函数的特殊语法。默认的 match() 函数实现引发异常并且对任何事情都没有真正的用处。但是扩展可以用更有用的逻辑覆盖 match() 函数。

提取运算符充当函数“->”() 和“->>”() 的特殊语法。这些函数的默认实现执行JSON 子组件提取,但扩展可以覆盖它们用于其他目的。

6. BETWEEN运算符

BETWEEN 运算符在逻辑上等同于一对比较。x BETWEEN y AND z ”等同于“ x >= y AND x <= z ”,除了对于 BETWEEN,x表达式只计算一次。

7. CASE表达式

CASE 表达式的作用类似于其他编程语言中的 IF-THEN-ELSE。

出现在 CASE 关键字和第一个 WHEN 关键字之间的可选表达式称为“基本”表达式。CASE 表达式有两种基本形式:有基本表达式的和没有基本表达式的。

在没有基本表达式的 CASE 中,对每个 WHEN 表达式求值,并将结果视为布尔值,从最左边开始,向右继续。CASE 表达式的结果是对对应于第一个 WHEN 表达式求值为真的 THEN 表达式的求值。或者,如果没有 WHEN 表达式的计算结果为真,则计算 ELSE 表达式的结果(如果有)。如果没有 ELSE 表达式并且 WHEN 表达式都不为真,则总体结果为 NULL。

在评估 WHEN 项时,NULL 结果被认为是不正确的。

在具有基础表达式的 CASE 中,基础表达式仅被评估一次,并将结果与​​每个 WHEN 表达式的评估从左到右进行比较。CASE 表达式的结果是对应于比较为真的第一个 WHEN 表达式的 THEN 表达式的求值。或者,如果没有 WHEN 表达式的计算结果等于基本表达式的值,则计算 ELSE 表达式的结果(如果有)。如果没有 ELSE 表达式并且没有 WHEN 表达式产生等于基本表达式的结果,则总体结果为 NULL。

将基本表达式与 WHEN 表达式进行比较时,相同的整理顺序、关联和 NULL 处理规则适用,就好像基本表达式和 WHEN 表达式分别是=运算符的左侧和右侧操作数一样

如果基本表达式为 NULL,则 CASE 的结果始终是评估 ELSE 表达式(如果存在)的结果,如果不存在则为 NULL。

CASE 表达式的两种形式都使用惰性或短路求值。

以下两个 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 运算符的右侧可以是表表值函数 在这种情况下,右侧被理解为“(SELECT * FROM name )”形式的子查询。当右操作数为空集时,IN 的结果为假,NOT IN 的结果为真,无论左操作数如何,即使左操作数为 NULL。

IN 或 NOT IN 运算符的结果由以下矩阵确定:

Left operand
is NULL
Right operand
contains NULL
Right operand
is an empty set
Left operand found
within right operand
Result of
IN operator
Result of
NOT IN operator
no no no no false true
does not matter no yes no false true
no does not matter no yes true false
no yes no no NULL NULL
yes does not matter no does not matter NULL NULL

请注意,SQLite 允许 IN 或 NOT IN 运算符右侧带括号的标量值列表为空列表,但大多数其他 SQL 数据库引擎和 SQL92 标准要求该列表至少包含一个元素。

9.表列名称

列名可以是CREATE TABLE 语句中定义的任何名称或以下特殊标识符之一:“ ROWID ”、“ OID ”或“ _ROWID_ ”。这三个特殊标识符描述了与每个表的每一行关联的唯一整数键( rowid ),因此在WITHOUT ROWID表上不可用。如果CREATE TABLE 语句未定义具有相同名称的实际列,则特殊标识符仅引用行键。rowid 可以用在任何可以使用常规列的地方。

10. EXISTS 运算符

EXISTS 运算符的计算结果始终为整数值 0 和 1 之一。如果执行指定为 EXISTS 运算符右侧操作数的 SELECT 语句将返回一行或多行,则 EXISTS 运算符的计算结果为 1。如果执行 SELECT将根本不返回任何行,那么 EXISTS 运算符的计算结果为 0。

SELECT 语句返回的每行中的列数(如果有)和返回的具体值对 EXISTS 运算符的结果没有影响。特别是,包含 NULL 值的行与没有 NULL 值的行的处理方式没有任何不同。

11.子查询表达式

括号中SELECT语句是子查询。所有类型的 SELECT 语句,包括聚合和复合 SELECT 查询(使用 UNION 或 EXCEPT 等关键字的查询)都可以作为标量子查询。子查询表达式的值是封闭的SELECT语句结果的第一行。如果封闭的SELECT语句不返回任何行 ,则子查询表达式的值为 NULL 。

返回单个列的子查询是标量子查询,几乎可以在任何地方使用。返回两列或多列的子查询是行值 子查询,只能用作比较运算符的操作数。

12.相关子查询

用作标量子查询或用作 IN、NOT IN 或 EXISTS 表达式的右侧操作数的 SELECT 语句可能包含对外部查询中列的引用这样的子查询称为相关子查询。每次需要相关子查询的结果时,都会重新评估相关子查询。不相关的子查询只被评估一次,结果在必要时被重用。

13. CAST 表达式

“CAST( expr AS type-name )”形式的 CAST 表达式用于将expr的值转换为由type-name指定的不同存储类CAST 转换类似于将列亲和力应用于值时发生的转换,不同之处在于使用 CAST 运算符时,即使转换有损且不可逆,转换也会始终发生,而列亲和力仅更改值的数据类型如果更改是无损且可逆的。

如果expr的值为 NULL,则 CAST 表达式的结果也为 NULL。否则,结果的存储类是通过将用于确定列关联性的规则应用到类型名来确定的。

Affinity of type-name Conversion Processing
NONE Casting a value to a type-name with no affinity causes the value to be converted into a BLOB. Casting to a BLOB consists of first casting the value to TEXT in the encoding of the database connection, then interpreting the resulting byte sequence as a BLOB instead of as TEXT.
TEXT To cast a BLOB value to TEXT, the sequence of bytes that make up the BLOB is interpreted as text encoded using the database encoding.

Casting an INTEGER or REAL value into TEXT renders the value as if via sqlite3_snprintf() except that the resulting TEXT uses the encoding of the database connection.

REAL When casting a BLOB value to a REAL, the value is first converted to TEXT.

When casting a TEXT value to REAL, the longest possible prefix of the value that can be interpreted as a real number is extracted from the TEXT value and the remainder ignored. Any leading spaces in the TEXT value are ignored when converging from TEXT to REAL. If there is no prefix that can be interpreted as a real number, the result of the conversion is 0.0.

INTEGER When casting a BLOB value to INTEGER, the value is first converted to TEXT.

When casting a TEXT value to INTEGER, the longest possible prefix of the value that can be interpreted as an integer number is extracted from the TEXT value and the remainder ignored. Any leading spaces in the TEXT value when converting from TEXT to INTEGER are ignored. If there is no prefix that can be interpreted as an integer number, the result of the conversion is 0. If the prefix integer is greater than +9223372036854775807 then the result of the cast is exactly +9223372036854775807. Similarly, if the prefix integer is less than -9223372036854775808 then the result of the cast is exactly -9223372036854775808.

When casting to INTEGER, if the text looks like a floating point value with an exponent, the exponent will be ignored because it is no part of the integer prefix. For example, "(CAST '123e+5' AS INTEGER)" results in 123, not in 12300000.

The CAST operator understands decimal integers only — conversion of hexadecimal integers stops at the "x" in the "0x" prefix of the hexadecimal integer string and thus result of the CAST is always zero.

A cast of a REAL value into an INTEGER results in the integer between the REAL value and zero that is closest to the REAL value. If a REAL is greater than the greatest possible signed integer (+9223372036854775807) then the result is the greatest possible signed integer and if the REAL is less than the least possible signed integer (-9223372036854775808) then the result is the least possible signed integer.

Prior to SQLite version 3.8.2 (2013-12-06), casting a REAL value greater than +9223372036854775807.0 into an integer resulted in the most negative integer, -9223372036854775808. This behavior was meant to emulate the behavior of x86/x64 hardware when doing the equivalent cast.

NUMERIC Casting a TEXT or BLOB value into NUMERIC yields either an INTEGER or a REAL result. If the input text looks like an integer (there is no decimal point nor exponent) and the value is small enough to fit in a 64-bit signed integer, then the result will be INTEGER. Input text that looks like floating point (there is a decimal point and/or an exponent) and the text describes a value that can be losslessly converted back and forth between IEEE 754 64-bit float and a 51-bit signed integer, then the result is INTEGER. (In the previous sentence, a 51-bit integer is specified since that is one bit less than the length of the mantissa of an IEEE 754 64-bit float and thus provides a 1-bit of margin for the text-to-float conversion operation.) Any text input that describes a value outside the range of a 64-bit signed integer yields a REAL result.

Casting a REAL or INTEGER value to NUMERIC is a no-op, even if a real value could be losslessly converted to an integer.

请注意,将任何非 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)被认为是错误的。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 的别名。但是,如果 IS 运算符的右侧出现 TRUE 或 FALSE,则 IS 运算符会将左侧操作数计算为布尔值并返回适当的答案。

15.函数

SQLite 支持许多simpleaggregatewindow SQL 函数。出于演示目的,简单函数进一步细分为核心函数日期时间函数JSON 函数应用程序可以使用sqlite3_create_function()接口 添加用 C/C++ 编写的新函数 。

上面的主表达式气泡图显示了所有函数调用的单一语法。但这仅仅是为了简化表达气泡图。实际上,每种函数的语法略有不同,如下所示。主表达式气泡图中显示的函数调用语法是此处显示的三种语法的联合:

简单函数调用:

simple-func ( expr ) , *

聚合函数调用:

aggregate-func ( DISTINCT expr ) filter-clause , *

窗口函数调用:

window-func ( expr ) filter-clause OVER window-name window-defn , *

OVER 子句对于窗口函数是必需的,否则是禁止的。DISTINCT 关键字只允许在聚合函数中使用。FILTER 子句可能不会出现在简单的函数中。

只要函数的两种形式的参数数量不同,就可以有一个与简单函数同名的聚合函数。例如,具有单个参数的max()函数是一个聚合函数,而具有两个或多个参数的max()函数是一个简单函数。聚合函数通常也可以用作窗口函数。