Small. Fast. Reliable.
Choose any three.
SQL语言表达式

1.语法

expr:

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 ESCAPE expr expr ISNULL NOTNULL NOT NULL expr IS NOT 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

过滤器子句:

文字值:

子句:

提升功能:

select-stmt:

类型名称:

2.运营商

SQLite理解以下二进制运算符,从最高优先级到最低优先级:

||
* /%
+-
<< >>&|
<<=>> =
= ==!= <>   不像GLOB MATCH REGEXP
和   
或者

支持的一元前缀运算符如下:

-+〜不

COLLATE运算符是一元后缀运算符,用于将排序顺序分配给表达式。COLLATE运算符的优先级(绑定更紧密)比任何二进制运算符和除“〜”之外的任何一元前缀运算符都高。(COLLATE和“〜”是关联的,因此它们的绑定顺序无关紧要。)COLLATE运算符设置的整理顺序将覆盖表列定义中COLLATE子句确定的整理顺序 。有关其他信息,请参见SQLite3 中的数据类型中有关整理序列详细讨论

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

请注意,等于和不等于运算符有两种变体。等于可以是 ===。非等于运算符可以是 !=<>。该|| 运算符是“串联的”-将其操作数的两个字符串连接在一起。在运营蒙上它的两个操作数整数类型,然后由右整划分左整后计算的余数。

除了||以外,任何二进制运算符的结果都是数值或NULL。并置运算符,该运算符始终求值为NULL或文本值。

ISIS NOT像运营商的工作=!=除非操作数的一方或双方为NULL。在这种情况下,如果两个操作数均为NULL,则IS运算符的计算结果为1(true),而IS NOT运算符的计算结果为0(false)。如果一个操作数为NULL,另一个则为NULL,则IS运算符的计算结果为0(假),而IS NOT运算符的计算结果为1(真)。IS或IS NOT表达式无法计算为NULL。运算符ISIS NOT的优先级与=相同。

3.文字值(常量)

文字值表示一个常数。文字值可以是整数,浮点数,字符串,BLOB或NULL。

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

数字字面量:

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

如果数字文字具有小数点或幂运算子句,或者其大小小于-922337203685477575808或大于9223372036854775807,则它是浮点文字。否则,它是整数文字。浮点文字的幂运算子句开头的“ E”字符可以是大写或小写。这 ”。” 即使语言环境设置为此角色指定“,”,也始终将字符用作小数点-对于小数点使用“,”将导致句法歧义。

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

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

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

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

4.参数

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

神经网络 问号后跟数字NNN表示第NNN个参数。NNN必须介于1到SQLITE_MAX_VARIABLE_NUMBER之间。
没有数字的问号会创建一个参数,该参数的数字比已分配的最大参数数字大一。如果这意味着参数编号大于 SQLITE_MAX_VARIABLE_NUMBER,则为错误。提供此参数格式是为了与其他数据库引擎兼容。但是,由于很容易误解问号,因此不建议使用此参数格式。鼓励程序员改用下面的符号格式之一或上面的?NNN格式。
AAAA 冒号后跟标识符名称会保留一个名为:AAAA的 命名参数的位置。命名的参数也已编号。分配的编号比已经分配的最大参数编号大一。如果这意味着将为该参数分配一个大于SQLITE_MAX_VARIABLE_NUMBER的数字,则错误。为避免混淆,最好避免混合命名和编号的参数。
@ AAAA 除了创建的参数名称为@AAAA以外,“ at”符号的工作原理与冒号完全相同。
$ 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运算符

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

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

通过调用应用程序定义的SQL函数like(YXlike(YXZ来实现infix LIKE运算符。

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

GLOB运算符与LIKE相似,但其通配符使用Unix文件全局语法。此外,与LIKE不同,GLOB区分大小写。GLOB和LIKE都可以在NOT关键字之前,以反转测试的意义。通过调用函数glob(YX实现infix GLOB运算符 并且可以通过重写该函数来对其进行修改。

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

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

6. BETWEEN运算符

BETWEEN运算符在逻辑上等效于一对比较。“ x BETWEEN y AND z ”等效于“ x > = y AND x <= z ”,不同之处在于使用BETWEEN时,x表达式仅计算一次。BETWEEN运算符的优先级与运算符==!=以及LIKE和组从左到右的优先级相同。

7. CASE表达式

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

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

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

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

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

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

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

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

以下两个CASE表达式之间的唯一区别是,在第一个示例中,x表达式仅被评估一次,而在第二个示例中,x表达式可能被多次评估:

内置的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)”形式的子查询。当右操作数是一个空集时,无论左操作数如何,即使左操作数为NULL,IN的结果都为false,而NOT IN的结果为true。

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

左操作数
为NULL
右操作数
包含NULL
右操作数
是一个空集

在右操作数之内找到左操作数

IN运算符的 结果

NOT IN运算符的 结果
错误的 真的
没关系 是的 错误的 真的
没关系 是的 真的 错误的
是的 空值 空值
是的 没关系 没关系 空值 空值

请注意,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查询(带有UNION或EXCEPT之类的关键字的查询)在内的所有类型的SELECT语句都可以用作标量子查询。子查询表达式的值是附带的SELECT语句的结果的第一行。如果附带的SELECT语句不返回任何行,则子查询表达式的值为NULL 。

返回单列的子查询是标量子查询,可以在大多数地方使用。返回两列或更多列的 子查询是行值子查询,并且只能用作比较运算符的操作数。

12.相关子查询

SELECT语句用作一个标量子查询或作为右边的操作数的IN的,NOT IN或EXISTS表达可以包含在外部查询到列的引用。这样的子查询被称为相关子查询。每当需要其结果时,都会重新评估相关的子查询。不相关的子查询仅被评估一次,结果将根据需要重新使用。

13. CAST表达式

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

如果expr的值为NULL,则CAST表达式的结果也为NULL。否则,存储类的结果是通过应用所确定的规则来确定柱的亲类型名称

类型名称的相似性 转换处理
没有任何 将值强制转换为没有亲缘关系的类型名称会导致该值转换为BLOB。转换为BLOB的过程包括:首先在数据库连接的编码中将值转换为TEXT ,然后将结果字节序列解释为BLOB而不是TEXT。
文本 要将BLOB值转换为TEXT,构成BLOB的字节序列将解释为使用数据库编码方式编码的文本。

将INTEGER或REAL值强制转换为TEXT会像通过sqlite3_snprintf()一样呈现该值, 除了生成的TEXT使用数据库连接的编码

真实的 将BLOB值转换为REAL时,该值首先转换为TEXT。

将TEXT值转换为REAL时,将从TEXT值中提取可以解释为实数的值的最长前缀,其余部分将被忽略。从TEXT转换为REAL时,将忽略TEXT值中的任何前导空格。如果没有可以解释为实数的前缀,则转换结果为0.0。

整数 将BLOB值转换为INTEGER时,该值首先转换为TEXT。

当将TEXT值转换为INTEGER时,将从TEXT值中提取可以解释为整数的值的最大可能前缀,其余部分将被忽略。从TEXT转换为INTEGER时,TEXT值中的任何前导空格都将被忽略。如果没有可以解释为整数的前缀,则转换结果为0。如果前缀整数大于+9223372036854775807,则强制转换的结果为+9223372036854775807。同样,如果前缀整数小于-9223372036854775808,则强制转换的结果为-9223372036854775808。

强制转换为INTEGER时,如果文本看起来像是带有指数的浮点值,则该指数将被忽略,因为它不是整数前缀的一部分。例如,“((CAST'123e + 5'AS INTEGER)”)的结果为123,而不是12300000。

CAST运算符仅理解十进制整数-十六进制整数的转换在十六进制整数字符串的“ 0x”前缀中的“ x”处停止,因此CAST的结果始终为零。

将REAL值转换为INTEGER会导致REAL值和最接近REAL值的零之间的整数。如果REAL大于最大可能的带符号整数(+9223372036854775807),则结果为最大可能的带符号整数;如果REAL小于最小可能的带符号整数(-9223372036854775808),则结果为最小可能的带符号整数。

在SQLite版本3.8.2(2013-12-06)之前,将大于+9223372036854775807.0的REAL值转换为整数会导致负数最大,即-9223372036854775808。此行为旨在模拟进行等效转换时的x86 / x64硬件行为。

数字 将TEXT或BLOB值转换为NUMERIC会产生INTEGER或REAL的结果。如果输入文本看起来像一个整数(没有小数点也没有指数),并且该值足够小以适合64位带符号整数,则结果将是INTEGER。输入文本看起来像浮点数(有一个小数点和/或一个指数),并且该文本描述了一个可以在IEEE 754 64位浮点数和51位带符号整数之间无损地来回转换的值,然后结果是INTEGER。(在前面的句子中,指定了一个51位整数,因为它比IEEE 754 64位浮点数的尾数长度少一位,因此为文本到浮点转换提供了1位的余量。手术。

即使可以将实值无损地转换为整数,也不能将REAL或INTEGER值强制转换为NUMERIC。

请注意,根据数据库编码是UTF-8,UTF-16be还是UTF-16le ,将任何非BLOB值转换为BLOB的结果以及将任何BLOB值转换为非BLOB的结果可能会有所不同。。

14.布尔表达式

SQL语言具有几种上下文,在这些上下文中对表达式进行求值并将结果转换为布尔值(真或假)。这些上下文是:

要将SQL表达式的结果转换为布尔值,SQLite首先以与CAST表达式相同的方式将结果转换为NUMERIC值 。数字零值(整数值0或实数值0.0)被认为是错误的。NULL值仍为NULL。所有其他值都被认为是正确的。

例如,值NULL,0.0、0,“ english”和“ 0”都被视为false。值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 TRUE”和“ IS FALSE”,以测试左侧的操作数的布尔值。

15.功能

SQLite支持许多简单的聚合的窗口 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子句,否则禁止使用OVER子句。DISTINCT关键字仅在聚合函数中允许使用。FILTER子句可能不会出现在简单函数上

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