sqlite语法 (SQL)

官网:http://www.sqlite.org/lang.html (他人的中文翻译http://blog.csdn.net/ejzhang/article/details/6224915/#09
可视化工具可以用 Datum Free
SQL对大小写不敏感,但也有一些命令是大小写敏感的,比如 GLOB 和 glob 在 SQLite 的语句中有不同的含义。一般关键词大写

EXPLAIN


sql-stmt.gif

EXPLAIN命令主要用于辅助开发,用于输出sql命令的执行过程。

ANALYZE


analyze-stmt.gif

使用ANALYZE命令可以使系统收集表格(tables)和索引(indices)的统计数据,并存储到数据库的内部表格中(sqlite_stat开头的表格为内部表格,使用select等命令可以查询或修改内部表格数据,详情看官网介绍)。如果ANALYZE后面不带参数,则所有被连接的数据库都会被分析。
即使数据库的内容被修改了,通过ANALYZE命令收集的数据不会自动更新。如果数据库的内容有重大修改或者数据库结构改变,应该重新运行ANALYZE命令以更行采集数据。
由于读取数据库内容的时候,查询程序会将采集数据读取到缓存中,所以如果应用程序直接修改数据表格,数据库将不会立即响应,因此,应用程序应该通过执行ANALYZE sqlite_master命令强制查询程序重新读取数据表格中的采集数据。

一、创建处理

1、CREATE TABLE

create-table-stmt.gif

注:表格名不能以“sqlite_”开头,“sqlite_”为数据库预留开头

  • TEMP/TEMPORARY

"CREATE TEMP(TEMPORARY) TABLE"创建的是临时表格,临时表和与其相关的索引、触发器和视观表都存放在一个名为temp的临时数据库文件中。而名为temp的数据库文件是在第一次使用"CREATE TEMP(TEMPORARY) TABLE"的时候自动创建的。临时表格和名为temp的临时数据库文件会在数据库被关闭的时候会被自动删除。

  • column-def
column-def.gif
  • column-constraint
column-constraint.gif
  • 主键(Primary Key) //它是用来独一无二地确认一个表格中的每一行资料,可以同时为空值(不传值或传NULL)。新插入数据,如果该栏位的值已经存在,则插入语句执行失败,表格数据没变化。主键可以是原本资料内的一个栏位,或是一个人造栏位(与原本资料没有关系的栏位)。主键可以包含一或多个栏位。当主键包含多个栏位时,称为组合键(Composite Key)。

eg.
组合键create table test (name char(50),nameID char(50),constraint myKey primary key (name,nameID));
注释:name和nameID不能同时相等,多条数据name和nameID可同时等于NULL,constraint myKey可要可不要,

  • NOT NULL //没限制情况下,是允许有NULL值的
  • UNIQUE. //保证该栏位中所有资料的值都是不一样的,可以同时为空值(不传值或传NULL)。新插入数据,如果该栏位的值已经存在,则插入语句执行失败,表格数据没变化。
  • CHECK. //保证该栏位中所有资料的值都符合某些条件,用于限制列中的值的范围。(对应列不传值或传NULL不受限制)

eg.
1、CREATE TABLE Persons
(
Id_P int NOT NULL CHECK (Id_P>0),
LastName varchar(255) NOT NULL,
FirstName varchar(255),
Address varchar(255),
City varchar(255)
)
2、CREATE TABLE Persons
(
Id_P int NOT NULL,
LastName varchar(255) NOT NULL,
FirstName varchar(255),
Address varchar(255),
City varchar(255),
CONSTRAINT chk_Person CHECK (Id_P>0 AND City='Sandnes')
)
注:CONSTRAINT chk_Person可要可不要

  • COLLATE

collation-name:

  • BINARY - 使用 memcmp() 对字符串数据进行比较,无论文本编码。
  • NOCASE - 与 BINARY 相同,除了在比较执行之前会将 ASCII 码的 26 个大写字母被折换为与其等值的小写字母。注意,只有 ASCII 码的字符进行大小写折换。由于所需表的大小,SQLite 不会尝试对完整 UTF 的大小写进行折换。
  • RTRIM - 与 BINARY 相同,除了尾随的空格将被忽略。

校对规则:
每个表的每个列都有一个相关联的校对函数。如果没有校对函数被明确定义,校对规则默认为 BINARY。列定义的 COLLATE 子句被用来替代地为一个列定义校对函数。
为一个二元比较操作符(=、<、>、<=、>=、!=、IS 和 IS NOT)决定使用何种校对函数,按照下面展示的规则顺序进行:

1、如果两个操作数都使用 COLLATE 后缀操作符分配了一个明确的校对函数,那么明确的校对函数被用在比较中,左边操作数的校对函数有较高的优先级。
2、如果两个操作数都是一个列,左边列的校对函数有较高的优先级。前一句的目的是,带有一个或多个一元“+”操作符的列名仍被认为是一个列名。
3、否则,比较将会使用 BINARY 校对函数。

表达式“x BETWEEN y AND z”在逻辑上等价于两个比较“x >= y AND x <= z”,并且与校对函数一起工作,就像这是有两个分开的比较一样。表达式“x IN (SELECT y ...)”与“x = y”的处理方式一样,目的是为了确定校对序列。用在“x IN (y z ...)”格式表达式上的校对序列,就是 x 的校对序列。
ORDER BY 子句是一个 SELECT 语句的一部分,其规则是,可使用 COLLATE 操作符为 SELECT 语句分配一个校对序列,在这种情况下,特定的校对函数被用于排序。否则,如果通过 ORDER BY 子句进行排序的表达式是一个列,列的校对序列将被用来确定排序顺序。如果表达式不是一个列并且没有 COLLATE 子句,则 BINARY 校对序列将被使用。

  • 外来键(Foreign Key) //一般,外来键指向主键,也可以指向UNIQUE修饰的列或拥有UNIQUE index的列。update或者insert的时候,外来键对应的值可为NULL

eg.
CREATE TABLE ORDERS (Order_ID integer primary key,Order_Date datetime,Customer_SID integer references CUSTOMER(SID),Amount double);

CREATE TABLE parent(a PRIMARY KEY, b UNIQUE, c, d, e, f);
CREATE UNIQUE INDEX i1 ON parent(c, d);
CREATE INDEX i2 ON parent(e);
CREATE UNIQUE INDEX i3 ON parent(f COLLATE nocase);
CREATE TABLE child1(f, g REFERENCES parent(a)); -- Ok
CREATE TABLE child2(h, i REFERENCES parent(b)); -- Ok
CREATE TABLE child3(j, k, FOREIGN KEY(j, k) REFERENCES parent(c, d)); -- Ok
CREATE TABLE child4(l, m REFERENCES parent(e)); -- Error!
CREATE TABLE child5(n, o REFERENCES parent(f)); -- Error!
CREATE TABLE child6(p, q, FOREIGN KEY(p, q) REFERENCES parent(b, c)); -- Error!
CREATE TABLE child7(r REFERENCES parent(c)); -- Error!

注:sqlite默认是关闭外来键功能的,在使用该约束之前,需要开外来键功能:PRAGMA foreign_keys = ON(FMDB:[_db executeUpdate:@"PRAGMA foreign_keys = ON"];)

CUSTOMER 表格

栏位名 性质
SID 主键
Last_Name
First_Name

ORDERS表格

栏位名 性质
Order_ID 主键
Order_Date
Customer_SID 外来键
Amount
  • table-constraint
table-constraint.gif
  • AS select-stmt

根据查询数据创建表格,该方法创建的表格没有primary key和其他对表格或数据的限制
CREATE TABLE "表格名" AS SELECT...
eg.create table new as select * from otherTableName;

  • WITHOUT ROWID //sqlite数据库表格默认存在一个名为“rowid”的列,建表的时候,使用该约束,则表中不存在“rowid”列。参考网址:http://www.sqlite.org/withoutrowid.html 。使用该约束的一些限制如下:

(1)必须存在primary key,否则报错
(2)不能使用AUTOINCREMENT
(3)使用该约束后,表格的PRIMARY KEY 对应的值不能为NULL

2、CREATE VIEW

视观表(Views)可以被当作是虚拟表格。它跟表格的不同是,表格中有实际储存资料,而视观表是建立在表格之上的一个架构,它本身并不实际储存资料。


create-view-stmt.gif

如果column-name有值,则创建的view用column-name中的值做列名,否则用select-stmt结果做列名

eg.
(1)针对单个表创建视观表

CREATE VIEW view_name AS SELECT column_name(s) FROM table_name WHERE condition
eg.
有表格:TABLE Customer (First_Name char(50),Last_Name char(50),Address char(50))
创建对应的视观表:CREATE VIEW V_Customer AS SELECT First_Name, Last_Name FROM Customer

(2)针对多个表创建视观表

CREATE VIEW V_REGION_SALES AS SELECT A1.region_name REGION, SUM(A2.Sales) SALES FROM Geography A1, Store_Information A2 WHERE A1.store_name = A2.store_name GROUP BY A1.region_name

Store_Information 表格

store_name Sales Date
Los Angeles $1500 Jan-05-1999
San Diego $250 Jan-07-1999
Los Angeles $300 Jan-08-1999
Boston $700 Jan-08-1999

Geography 表格

region_name store_name
East Boston
East New York
West Los Angeles
West San Diego

V_REGION_SALES结果如下

REGION SALES
East $700
West $2050

3、CREATE INDEX

您可以在表中创建索引,以便更加快速高效地查询数据。
用户无法看到索引,它们只能被用来加速搜索/查询。


create-index-stmt.gif

注释:更新一个包含索引的表需要比更新一个没有索引的表更多的时间,这是由于索引本身也需要更新。因此,理想的做法是仅仅在常常被搜索的列(以及表)上面创建索引。

4、CREATE TRIGGER

create-trigger-stmt.gif
  • SQLite 只支持 FOR EACH ROW 触发器(Trigger),没有 FOR EACH STATEMENT 触发器(Trigger)。因此,明确指定 FOR EACH ROW 是可选的。

  • WHEN 子句和触发器(Trigger)动作可能访问使用表单 NEW.column-name 和 OLD.column-name 的引用插入、删除或更新的行元素,其中 column-name 是从与触发器关联的表的列的名称。OLD和NEW的使用情况如下:

  • INSERT -- NEW可以使用

  • UPDATE -- NEW和OLD都可以使用

  • DELETE -- OLD可以使用

  • 如果提供 WHEN 子句,则只针对 WHEN 子句为真的指定行执行 SQL 语句。如果没有提供 WHEN 子句,则针对所有行执行 SQL 语句。

  • “ ON CONFLICT”可以指定为触发器内部的更新或插入操作的一部分。但是如果将“ ON CONFLICT”子句指定为引发触发器的语句的一部分,则使用外部语句的冲突处理策略来代替触发器。

  • 当触发器相关联的表删除时,自动删除触发器(Trigger)。如果触发器与其他表格链接,则那些表格被删除或者修改,触发器不会被删除或者修改

触发器中DELETE,UPDATE,INSERT语句的一些限制如下:

  • 在DELETE,UPDATE,INSERT语句对应的表的名称必须是绝对的表名。换句话说,必须只使用“表”而不是“数据库.表的”。要修改的表必须存在于与触发器关联的表或视观表的同一数据库中。
  • 不支持 "INSERT INTO table DEFAULT VALUES" 形式的 INSERT语句

  • UPDATE和DELETE语句不支持“INDEXED BY”和“NOT INDEXED”分句

  • UPDATE和DELETE语句不支持ORDER BY和LIMIT分句

  • 触发器内不支持“Common table expression”

  • INSTEAD OF triggers

通过在创建触发器的时候指定INSTEAD OF,除了可以创建基于普通表的触发器,还可以创建基于视观表(views)的触发器。如果不创建对应的触发器,当对视观表(views)修改的时候,真实表的数据将不会跟随着改变。

二、ALTER TABLE

alter-table-stmt.gif
  • RENAME

如果表格有触发器和索引,重命名后,这些触发器和索引依然和表哥链接。但是,如果有视观表定义或通过触发器执行的命令参考了表格,则表格重命名后,不会自动修改表格名。如果有需要,视观表定义和触发器必须删掉重新用新表格名创建。
如果开了外来键,则表格重命名后,外来键定义会对应于新表格名被自动修改

三、DROP

  • DROP TABLE


    drop-table-stmt.gif

    如果开了外来键(foreign key)功能,在删除表格之前,系统会执行DELETE FROM命令。在执行DELETE FROM命令前,所有的触发器(triggers)会被删除,所以删除表格命令不会触发触发器。DELETE FROM操作会触发外来键相关操作。

  • DROP VIEW


    drop-view-stmt.gif
  • DROP TRIGGER


    drop-trigger-stmt.gif
  • DROP INDEX


    drop-index-stmt.gif

四、INSERT/REPLACE

insert-stmt.gif
  • culumn-name

如果省略column-name项,则插入每行的值的数量必须和表格的列数目相同。如果使用column-name项,则插入每行的值的数量和column-name清单数量相同。如果column-name清单中没有的列,插入的时候则使用默认值或者NUll。

  • VALUES (...)

用于创建一个或多个新行。

  • select-stmt

用于将select-stmt的结果插入表格中。

  • DEFAULT

插入的行的数值使用默认值,如果没有默认值,则为NULL

五、 UPDATE

update-stmt.gif

六、 DELETE

delete-stmt.gif

七、SELECT

select-stmt.gif

八、TRANSACTION(事务)

1、 begin-stmt


begin-stmt.gif

2、 commit/end-stmt


commit-stmt.gif

3、 rollback-stmt


rollback-stmt.gif

对数据库的修改都是通过事务实现的,除了select外的所有修改数据库的命令都会自动启动一事务处理,完成之后自动关闭事务。此外,事务也可以用BEGIN命令手动开启。当执行commit/end、rollback或者数据库被关闭、设定用rollback解决的冲突(conflict)发生的时候,事务会被关闭。

  • deferred

此为事务的默认类型,对于该类型的事务,直到对数据库进行读写操作的时候才会获取数据库的锁,首次读的时候会获取SHARED锁,首次写的时候会获取RESERVED锁。
当执行commit命令的时候,如果其他线程持有shared锁,则返回结果为SQLITE_BUSY。对于这种commit失败,线程会保持,并可以再次尝试commit

  • immediate

对于该类型的事务,在执行begin命令后就会获取数据库的RESERVED锁。

  • exclusive

该类型事务,在执行bigin命令后就会获取数据库的exclusive锁。

sqlite有五种锁:

  • 未加锁(UNLOCKED)
    文件没有持有任何锁,即当前数据库不存在任何读或写的操作。其它的进程可以在该数据库上执行任意的读写操作。此状态为缺省状态。
  • 共享锁(SHARED)
    在此状态下,该数据库可以被读取但是不能被写入。在同一时刻可以有任意数量的进程在同一个数据库上持有共享锁,因此读操作是并发的。换句话说,只要有一个或多个共享锁处于活动状态,就不再允许有数据库文件写入的操作存在。
  • 保留锁(RESERVED)
    假如某个进程在将来的某一时刻打算在当前的数据库中执行写操作,然而此时只是从数据库中读取数据,那么我们就可以简单的理解为数据库文件此时已经拥有了保留锁。当保留锁处于活动状态时,该数据库只能有一个或多个共享锁存在,即同一数据库的同一时刻只能存在一个保留锁和多个共享锁. 需要说明的是update操作 实际上是一个读操作加一个写操作
  • 未决锁(PENDING)
    PENDING锁的意思是说,某个进程正打算在该数据库上执行写操作,然而此时该数据库中却存在很多共享锁(读操作),那么该写操作就必须处于等待状态,即等待所有共享锁消失为止,与此同时,新的读操作将不再被允许,以防止写锁饥饿的现象发生。在此等待期间,该数据库文件的锁状态为PENDING,在等到所有共享锁消失以后,PENDING锁状态的数据库文件将在获取排他锁之后进入EXCLUSIVE状态。
  • 排它锁(EXCLUSIVE)
    在执行写操作之前,该进程必须先获取该数据库的排他锁。然而一旦拥有了排他锁,任何其它锁类型都不能与之共存。因此,为了最大化并发效率,SQLite将会最小化排他锁被持有的时间总量。

十、其他

1、ON CONFLICT clause

conflict-clause.gif
  • ON CONFLICT子句不是独立的SQL命令。这是一条可以出现在许多其他SQL命令中的非标准的子句。
  • ON CONFLICT子句的语法在如上的CREATE TABLE命令中示出。对于INSERT和UPDATE,关键词"ON CONFLICT"由"OR"替代,这样语法显得自然。例如,不用写"INSERT ON CONFLICT IGNORE"而是"INSERT OR IGNORE".二者表示相同的意思。
  • ON CONFLICT子句定义了解决约束冲突的算法。有五个选择:ROLLBACK, ABORT, FAIL, IGNORE, 和REPLACE.缺省方案是ABORT.选项含义如下:
  • ROLLBACK
    当发生约束冲突,命令中止正在执行的SQL语句并返回SQLITE_CONSTRAINT错误,同时ROLLBACK当前事务。若当前无活动事务(除了每一条命令创建的默认事务以外),则该算法与ABORT相同。
  • ABORT
    当发生约束冲突,命令收回正在执行的SQL语句已经引起的改变并中止正在执行的SQL语句返回SQLITE_CONSTRAINT错误。但前面的命令产生的改变将予以保留,并且当前事务保留。缺省采用这一行为。
  • FAIL
    当发生约束冲突,命令中止正在执行的SQL语句返回SQLITE_CONSTRAINT。但遇到冲突之前的所有改变将被保留,同时事务也保留。例如,若一条UPDATE语句在100行遇到冲突1,前99行的改变将被保留,而对100行或以后的改变将不会发生。
  • IGNORE
    当发生约束冲突,发生冲突的行将不会被插入或改变(即忽略当前SQL语句)。但命令将照常执行。在冲突行之前或之后的行将被正常的插入和改变,且不返回错误信息。
  • REPLACE
    当发生UNIQUE或者PRIMARY KEY冲突,先存在的,导致冲突的行在更改或插入发生冲突的行之前被删除。这样,更改和插入总是被执行。命令照常执行且不返回错误信息。当发生NOT NULL约束冲突,导致冲突的NULL值会被字段缺省值取代。若字段无缺省值,执行ABORT算法。如果CHECK约束发生冲突,则执行ABORT算法
    当冲突应对策略为满足约束而删除行时,它不会调用删除触发器,除非“recursive triggers”(循环触发器)被使能。

2. VACUUM

VACUUM 命令通过复制主数据库中的内容到一个临时数据库文件,然后清空主数据库,并从副本中重新载入原始的数据库文件。这消除了空闲页,把表中的数据排列为连续的,另外会清理数据库文件结构。

  • 除非SQLite运行在“auto_vacuum=FULL”模式,否则当从数据库文件中删除大量数据之后,就会留下很多空白空间,或者“空闲”的数据库页。这意味着数据库文件的大小会比(它所存储的数据)实际需要的(空间)更大。运行VACUUM命令将会重新构建数据库文件,回收空白空间,减小数据库文件的大小。
  • 频繁的插入,更新和删除操作,会导致数据库文件变得支离破碎(产生大量的内存碎片)——因为单独一个表中的数据或者索引可能会分散的存储在数据库文件中。运行VACUUM命令可以确保每个表(的数据)和索引可以最大限度的连续存储在数据库文件中。在某些情况下,VACUUM命令也会减少数据库中的一部分填充页面,从而进一步减小数据库文件的大小。
  • 通常情况下,数据库的page_size和数据库是否支持auto_vacuum(这些配置)都要在数据库文件实际创建之前进行配置。然而,如果SQLite不是运行在“写前日志(write-ahead log)”模式下,一个已经存在(已经创建)的数据库(文件)的page_size和/或auto_vacuum属性,可以使用page_size和/或auto_vacuum编译指示进行修改,然后立即清扫数据库。如果SQLite是运行在“写前日志”模式下,则只有(是否支持)auto_vacuum属性可以通过VACUUM命令进行修改。

VACUUM命令只能工作在主数据库上,不能用来“清扫”一个附加的数据库文件。

VACUUM命令通过如下方式进行工作:首先把数据库内容复制到一个临时数据库文件中,然后再把临时数据库文件中的内容写回到原始数据库文件中(以整理数据库文件)。当将内容重新写回到原始数据库文件时,一个回滚日志或者写前日志WAL文件将会被使用,正如它为其它数据库事务服务一样。这意味着当“清扫”一个数据库时,将需要使用高达两倍于原始数据库文件大小的空闲磁盘空间。

VACUUM命令可能会改变数据库表的行ID(ROWIDs),假如这个表没有一个显示的整形主键(INTEGER PRIMARY KEY)的话。

如果存在一个打开(open)的事务,或者存在一个或多个正在活动(活跃)的(active)SQL语句,那么VACUUM命令将会执行失败。

对于SQLite3.1,可以使用“auto-vacuum模式”代替“VACUUM命令”在删除数据后回收空间,可以通过使用auto_vacuum编译指示来使能auto-vacuum模式。使能auto_vacuum模式之后,一个数据库在删除数据后留下的空闲页就可能会被回收,从而缩小数据库文件,而不用使用VACUUM命令重新构建整个数据库。然而,使用auto_vacuum模式将会导致额外的数据库文件碎片。并且使用auto_vacuum模式不会压缩部分数据库的填充页而VACUUM命令则会(压缩)。

3、expression

expr.gif

这部分有别于其它部分。 本文档的其它大多数部分都在讲特定的 SQL 命令。 本部分所讲的不是一个单一的命令,而是“表达式”, 它经常用作其它命令的一部分来使用。

  • Operators

SQLite 有如下二元运算符,根据其优先级从高到低有:
||
* / %
+ -
<< >> & |
< <= > >=
= == != <> IS IS NOT IN LIKE GLOB MATCH REGEXP
AND
OR
以下是支持的一元运算符:
- + ~ NOT

COLLATE 运算符可以被看作是一个后置的一元运算符,除了“~”,它比一元运算符和二元运算符优先级更高。

"+"是no-op类一元运算符。 它可以被应用于字符串、数字、BLOB或NULL,并永远返回跟它作用的数值相同的结果。

两种变体的等号运算符和不等号运算符。等可以是 = 或 ==。 不等操作符有 != 或 <>。 || 运算符为“连接符”,它将两个字符串连接到一起。 % 输出其左边的数除以右面数后的余数。

除 || 之外, 任何二元操作符的结果都是一个数值型的值或者NULL。 || 返回text类型值或者NULL。

IS和IS NOT运算符,在一个或者两个操作数是NULL的时候,其和=与!=类似。IS和IS NOT运算符的结果只能是0或1,不会是NULL。

  • Literal Values (Constants)
    literal value表示一个常量,可以是integers、floating point numbers、strings、BLOBs或者NULL。
  • Parameters
    参数用于指定一个字面值在表达式中的存放位置。它将在运行时被使用 sqlite3_bind API 替换。 参数有如下几种格式:
---- ----
?NNN 问号后跟一个数字 NNN 用于存放第 NNN 个参数。NNN 必须在 1 到 SQLITE_MAX_VARIABLE_NUMBER 之间。
? 只有一个问号,它将用于存放紧跟其后的一个未用到的参数。
:AAAA 冒号后面跟一个标志符,用于存放名字为 AAAA 的变量。 命名的变量也会被编号,编号将使用第一个未被使用的编号。 为避免混淆,最好不要混用名字和编号作为参数。
@AAAA 一个 @ 符号等价于一个冒号。
$AAAA 美元符号后跟一个标志符也会存放名字为 AAAA 的参数。 在这种情况下,参数名字中可以出现很多“::”,并且,在“(…)”后缀中可以包含任何文本。 该语法是由 TCL 语言中相同的法而来的。

未使用 sqlite3_bind 来赋值的参数则认为是 NULL。

  • The LIKE, GLOB, REGEXP, and MATCH operators

LIKE 操作符会作一个模式匹配比较。 它右边是一个匹配模式,左边包含被匹配的字符串。 在匹配模式中,百分号 % 会匹配字符串中任意 0 个或多个字符。 一个下划线 _ 符号仅匹配一个任意的字符。 除此之外,其它的任何字符均只匹配它们自己 (在不区分大小写的环境下可能会匹配与之对应的大、小写字母)。 (也就是:SQLite中不区分大小写仅对 7 比特的拉丁字符有效, 对于 8 位的 iso8859 字符集UTF8字符则是区分大小写的)。 例如:表达式 ‘a’ LIKE ‘A’ 是 TRUE 但 ‘æ’ LIKE ‘Æ’ 则是 FALSE)。

若有可选的 ESCAPE 子句,那么 ESCAPE 关键字后的表达式必须是一个单个的字符(叫做转义字符)。 该字符可以用于 LIKE 模式字符串中来体现百分号或下划线。 转义字符后面的百分号或下划线均分别保持它们原来的意思。 中缀的 LIKE 操作符是使用 like(X,Y) 函数实现的。

中缀操作符 LIKE 是通过调用用户函数 like(X,Y) 实现的。

GLOB 操作符与 LIKE 类似,但它使用 Unix 通配符的的文件匹配语法。 并且,与 LIKE 不同, GLOB 是大小写敏感的。GLOB 和 LIKE 都可以用 NOT 关键字对匹配结果取反。 中缀的 GLOB 操作符是通过调用 用户函数 glob(X,Y) 实现的,可以通过该函数对其进行重载。

REGEXP 操作符是使用 regexp() 用户函数的一个特殊语法。 默认情况下, regexp() 用户函数没有定义,所以使用 REGEXP 将会出错。 如果在运行时增加一个名为 regexp 的用户定义函数, 则使用该操作符时将使用此函数来实现 REGEXP 功能。

MATCH 操作符是使用 match() 用户函数的一个特殊语法。 默认的 match() 函数实现只会引发一个异常,从而没多大用处。 但可以通过扩展该函数来实现更有用的逻辑。

  • The BETWEEN operator
    表达式“x BETWEEN y AND z”在逻辑上等价于两个比较“x >= y AND x <= z”

  • The CASE expression

一个CASE表达式的规则与IF-THEN-ELSE语法类似

在CASE主键和第一个WHEN主键之间的可选表达式被称为‘base’表达式。CASE有两种基本类型:有‘base’表达式和没‘base’表达式。

如果CASE表达式没有ELSE表达式,且没有WHEN表达式为true,则CASE的结果为NULL

WHEN模块中的结果如果是NULL,表示假。

‘base’表达式和WHEN表达式的比较,COLLAT、亲和类型和NULL处理规则相当于“ ‘base’表达式=WHEN表达式”

如果‘base’表达式为NULL,则CASE表达式执行ELSE部分,如果没有ELES部分,则CASE表达式返回值为NULL

e.g

  • 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
    注:第一中类型,x只被执行一次;第二种,x被执行多次

  • The IN and NOT IN operators
    IN 和 NOT IN 运算符左边为一表达式,右边是一列数据或者一个子查询。当右侧的操作数是已子查询的时候,子查询的列数目必须和左侧操作数的值的数目相同。如果左边不是多个值,则子查询的结果单一列。当右侧的操作数是一列值的时候,右侧操作数每个值都必须是纯值,且左侧必须是一纯值。如果右侧操作数为空集,则IN的结果是false,NOT IN的结果是true。

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
  • The EXISTS operator
    如果select-stmt有一行或多行结果,则EXISTS结果为1,否则为0

  • Subquery Expressions
    在括号内的select-stmt叫做subquery。subquery后面会添加‘LIMIT 1’

  • CAST expressions
    CAST(CAST(expr AS type-name))表达式的作用是将expo转换为type-name类型的存储类型。CAST是强制转换,不管数据是否丢失或者转换是否可逆。
    如果expr的值是NULL,则CAST的结果也是NULL。否则结果的存储类型由下表规则决定

Affinity of type-name Conversion Processing
NONE 值将会被转换为BLOB类型。在这个过程中,先将值转换为数据库编码的TEXT类型,然后再将结果的字节解析成BLOB。
TEXT 将BLOB类型值转换为TEXT类型,字节序列将通过数据库编码成TEXT类型;将INTEGER或REAL值转换为TEXT是通过sqlite3_snprintf()
REAL 当将BLOB值转换为REAL的时候,是先将值转换为TEXT类型;当将TEXT转换为REAL时,可以从TEXT中提取最长的可能被解释为REAL的前缀,忽略其余的值。TEXT中的任何前导空格将被忽略,当从TEXT到REAL。如果没有前缀可以被解释为REAL,转换的结果是0。
INTEGER 当将BLOB值转换为INTEGER的时候,是先将值转换为TEXT类型;当将TEXT转换为INTEGER时,可以从文本值中提取可以被解释为整数的最长可能的前缀,忽略其余的值。当从文本转换为整数时,文本值中的任何前导空格将被忽略。如果没有前缀可以被解释为整数,转换的结果是0。CAST只理解十进制整数,所以十六进制整数只停在“0x”前缀的“X”处,从而使CAST的结果总是零。将一个实值转换为整数,结果是在实值和零之间的整数,该值与实值最接近。如果实值大于最大可能的有符号整数(+ 922337203685477580),则结果是最大可能的有符号整数,如果实值小于可能的有符号整数(- 922337203685477580),则结果是至少可能的有符号整数。
NUMERIC 将TEXT或BLOB转换为NUMERIC(数值)首先将强制转换为REAL,然后当结果仅从REAL到INTEGER转换为无损可逆时,再将结果转换成INTEGER。这是SQLite中NUMERIC和INTEGER亲和表现不同 的唯一语境;将REAL或INTEGER转换为NUMERIC是no-op(无操作)的,即使REAL能无损转换为INTEGER。
  • Boolean Expressions
    将一个表达式的结果转换为boolean值,sqlite首先用CAST将结果转换为NUMERIC类型值,如果NUMERIC值为零(整形的0或浮点型的0.0),则认为是false;NULL值依然是NULL值;其他的所有值都为true。如:NULL,0.0,0,‘English’和‘0’被认为是false;1,1.0,0.1,-0.1和‘1English’被认为是true。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,126评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,254评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,445评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,185评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,178评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,970评论 1 284
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,276评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,927评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,400评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,883评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,997评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,646评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,213评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,204评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,423评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,423评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,722评论 2 345

推荐阅读更多精彩内容