CREATE TRIGGER
sql-statement ::= | CREATE [TEMP | TEMPORARY] TRIGGER trigger-name [ BEFORE | AFTER ] database-event ON [database-name .] table-name trigger-action |
sql-statement ::= | CREATE [TEMP | TEMPORARY] TRIGGER trigger-name INSTEAD OF database-event ON [database-name .] view-name trigger-action |
database-event ::= | DELETE | INSERT | UPDATE | UPDATE OF column-list |
trigger-action ::= | [ FOR EACH ROW | FOR EACH STATEMENT ] [ WHEN expression ] BEGIN trigger-step ; [ trigger-step ; ]* END |
trigger-step ::= | update-statement | insert-statement | delete-statement | select-statement |
CREATE TRIGGER语句用于向数据库schema中添加触发器。触发器是一些在特定的数据库事件(database-event) 发生时自动进行的数据库操作(trigger-action).
触发器可由在特殊表上执行的DELETE, INSERT, UPDATE等语句触发,或UPDATE表中特定的字段时触发。
现在SQLite仅支持FOR EACH ROW触发器,不支持FOR EACH STATEMENT触发。因此可以不用明确说明FOR EACH ROW .FOR EACH ROW的意思是由trigger-steps说明的SQL语句可能在(由WHEN子句决定的)数据库插入,更改或删除的每一行触发trigger.
WHEN子句和trigger-steps可以使用"NEW.column-name"和"OLD.column-name"的引用形式访问正在被插入,更改或 删除的行的元素,column-name是触发器关联的表中的字段名。OLD 和 NEW 引用只在触发器与之相关的trigger-event处可用,例如:
INSERT | NEW可用 |
UPDATE | NEW和OLD均可用 |
DELETE | OLD可用 |
当使用WHEN子句,trigger-steps只在WHEN子句为真的行执行。不使用WHEN时则在所有行执行。
trigger-time决定了trigger-steps执行的时间,它是相对于关联行的插入,删除和修改而言的。
作为的一部分trigger-step的UPDATE 或 INSERT可以使用ON CONFLICT子句。 但若触发trigger的语句使用了ON CONFLICT子句,则覆盖前述的ON CONFLICT子句所定义的冲突处理方法。
关联表被撤销时触发器被自动删除。
不仅在表上,在视图上一样可以创建触发器,在CREATE TRIGGER语句中使用INSTEAD OF即可。 若视图上定义了一个或多个ON INSERT, ON DELETE, ON UPDATE触发器,则相应地对视图执行INSERT,DELETE 或UPDATE语句 不会出错,而会触发关联的触发器。视图关联的表不会被修改。(除了由触发器进行的修改操作)。
Example:
假设"customers"表存储了客户信息,"orders"表存储了订单信息,下面的触发器确保当用户改变地址时所有的 关联订单地址均进行相应改变:
CREATE TRIGGER update_customer_address UPDATE OF address ON customers BEGIN UPDATE orders SET address = new.address WHERE customer_name = old.name; END;
定义了该触发器后执行如下语句:
UPDATE customers SET address = ’1 Main St.’ WHERE name = ’Jack Jones’;
会使下面的语句自动执行:
UPDATE orders SET address = ’1 Main St.’ WHERE customer_name = ’Jack Jones’;
注意,目前在有INTEGER PRIMARY KEY域的表上触发器可能工作不正常。若BEFORE触发器修改了一行的 INTEGER PRIMARY KEY域,而该域将由触发该触发器的语句进行修改,则可能根本不会修改该域。 可以用PRIMARY KEY字段代替INTEGER PRIMARY KEY字段来解决上述问题。
一个特殊的SQL函数RAISE()可用于触发器程序,使用如下语法:
raise-function ::= | RAISE ( ABORT, error-message ) | RAISE ( FAIL, error-message ) | RAISE ( ROLLBACK, error-message ) | RAISE ( IGNORE ) |
当触发器程序执行中调用了上述前三个之一的形式时,则执行指定的ON CONFLICT进程(ABORT, FAIL或者ROLLBACK) 且终止当前查询,返回一个SQLITE_CONSTRAINT错误并说明错误信息。
当调用RAISE(IGNORE),当前触发器程序的余下部分,触发该触发器的语句和任何之后的触发器程序被忽略并且 不恢复对数据库的已有改变。 若触发触发器的语句是一个触发器程序本身的一部分,则原触发器程序从下一步起继续执行。
使用DROP TRIGGER删除触发器。
CREATE VIEW
sql-command ::= | CREATE [TEMP | TEMPORARY] VIEW [database-name.] view-name AS select-statement |
CREATE VIEW命令为一个包装好的SELECT语句命名。当创建了一个视图,它可以用于其他SELECT的FROM字句中代替表名。
若"TEMP"或"TEMPORARY"关键字出现在"CREATE"和"VIEW"之间,则创建的视图仅对打开数据库的进程可见,且在数据库关闭时自动删除。
若指定了则视图在指定的数据库中创建。同时使用和TEMP关键字会导致错误,除非是 "temp".若不声明数据库名,也不使用TEMP关键字,则视图创建于主数据库中。
你不能对视图使用COPY, DELETE, INSERT 或 UPDATE,视图在SQLite中是只读的。多数情况下你可以在视图上创建TRIGGER来达到相同目的。用DROP VIEW 命令来删除视图。
DELETE
sql-statement ::= | DELETE FROM [database-name .] table-name [WHERE expr] |
DELETE命令用于从表中删除记录。命令包含"DELETE FROM"关键字以及需要删除的记录所在的表名。
若不使用WHERE子句,表中的所有行将全部被删除。否则仅删除符合条件的行。
DETACH DATABASE
sql-command ::= | DETACH [DATABASE] database-name |
该语句拆分一个之前使用ATTACH DATABASE语句附加的数据库连接。可以使用不同的名字多次附加同一数据库,并且拆分一个连接不会影响其他连接。
若SQLite在事务进行中,该语句不起作用。
DROP INDEX
sql-command ::= | DROP INDEX [IF EXISTS] [database-name .] index-name |
DROP INDEX语句删除由CREATE INDEX 语句创建的索引。索引将从数据库结构和磁盘文件中完全删除,唯一的恢复方法是重新输入相应的CREATE INDEX命令。
DROP TABLE语句在缺省模式下不减小数据库文件的大小。空间会留给后来的INSERT语句使用。要释放删除产生的空间,可以使用VACUUM命令。若AUTOVACUUM模式开启,则空间会自动被DROP INDEX释放。
DROP TABLE
sql-command ::= | DROP TABLE [IF EXISTS] [database-name.] table-name |
DROP TABLE语句删除由 CREATE TABLE语句创建的表。表将从数据库结构和磁盘文件中完全删除,且不能恢复。该表的所有索引也同时被删除。
DROP TABLE语句在缺省模式下不减小数据库文件的大小。空间会留给后来的INSERT语句使用。要释放删除产生的空间,可以使用 VACUUM 命令。若AUTOVACUUM模式开启,则空间会自动被DROP TABLE释放。
若使用可选的IF EXISTS子句,在删除的表不存在时就不会报错。
DROP TRIGGER
sql-statement ::= | DROP TRIGGER [database-name .] trigger-name |
DROP TRIGGER语句删除由 CREATE TRIGGER创建的触发器。触发器从数据库的schema中删除。注意当关联的表被撤消时触发器自动被删除。
DROP VIEW
sql-command ::= | DROP VIEW view-name |
DROP VIEW语句删除由CREATE VIEW 创建的视图。视图从数据库的schema中删除,表中的数据不会被更改。
EXPLAIN
sql-statement ::= | EXPLAIN sql-statement |
EXPLAIN命令修饰语是一个非标准的扩展功能,灵感来自PostgreSQL中的相同命令,但操作完全不同。
若EXPLAIN关键字出现在任何SQLite SQL命令之前,则SQLite库返回不加EXPLAIN时执行该命令所需要使用的虚拟机指令序列,而不是真正执行该命令。关于虚拟机指令的更多信息参见系统结构描述或关于虚拟机的可用代码。
SELECT
sql-statement ::= | SELECT [ALL | DISTINCT] result [FROM table-list] [WHERE expr] [GROUP BY expr-list] [HAVING expr] [compound-op select]* [ORDER BY sort-expr-list] [LIMIT integer [( OFFSET | , ) integer]] |
result ::= | result-column [, result-column]* |
result-column ::= | * | table-name . * | expr [ [AS] string ] |
table-list ::= | table [join-op table join-args]* |
table ::= | table-name [AS alias] | ( select ) [AS alias] |
join-op ::= | , | [NATURAL] [LEFT | RIGHT | FULL] [OUTER | INNER | CROSS] JOIN |
join-args ::= | [ON expr] [USING ( id-list )] |
sort-expr-list ::= | expr [sort-order] [, expr [sort-order]]* |
sort-order ::= | [ COLLATE collation-name ] [ ASC | DESC ] |
compound_op ::= | UNION | UNION ALL | INTERSECT | EXCEPT |
SELECT语句用于查询数据库。一条SELECT命令的返回结果是零或多行每行有固定字段数的数据。字段的数目由在SELECT和FROM之间的表达式列表定义。任意的表达式都可以被用作结果。若表达式是 *则表示所有表的所有字段。若表达式是表的名字后接.*则结果为该表中的所有字段。
DISTINCT关键字的使用会使返回的结果是原结果的一个不含相同行的子集。NULL值被认为是相同的。缺省行为是返回所有的行,为清楚起见可以使用关键字ALL。
查询对FROM之后定义的一个或多个表进行。若多个表用逗号连接,则查询针对它们的交叉连接。所有的SQL-92连接语法均可以用于定义连接。圆括号中的副查询可能被FROM子句中的任意表名替代。当结果中仅有一行包含表达式列表中的结果的行时,整个的FROM子句会被忽略。
WHERE子句可以限定查询操作的行数目。
GROUP BY子句将一行或多行结果合成单行输出。当结果有聚集函数时这将尤其有用。GROUP BY子句的表达式不须是出现在结果中的表达式。HAVING子句与WHERE相似,只是HAVING用于过滤分组创建的行。HAVING子句可能包含值,甚至是不出现在结果中的聚集函数。
ORDER BY子句对所得结果根据表达式排序。表达式无须是简单SELECT的结果,但在复合SELECT中每个表达式必须精确对应一个结果字段。每个表达式可能跟随一个可选的COLLATE关键字以及用于排序文本的比较函数名称和/或关键字ASC或DESC,用于说明排序规则。
LIMIT子句限定行数的最大值。负的LIMIT表示无上限。后跟可选的OFFSET说明跳过结果集中的前多少行。在一个复合查询中,LIMIT子句只允许出现在最终SELECT语句中。限定对于所有的查询均适用,而不仅仅是添加了LIMIT子句的那一行。注意OFFSET关键字用于LIMIT子句中,则限制值是第一个数字,而偏移量(offset)是第二个数字。若用逗号替代OFFSET关键字,则偏移量是第一个数字而限制值是第二个数字。这是为了加强对遗留的SQL数据库的兼容而有意造成的矛盾。
复合的SELECT由两个或更多简单SELECT经由UNION, UNION ALL, INTERSECT, EXCEPT中的一个运算符连接而成。在一个复合SELECT中,各个SELECT需指定相同个数的结果字段。仅允许一个ORDER BY子句出现在SELECT的末尾。UNION和UNION ALL运算符从左至右将所有SELECT的结果合成一个大的表。二者的区别在于UNION的所有结果行是不相同的而 UNION ALL允许重复行。INTERSECT运算符取左右两个SELECT结果的交。EXCEPT从左边SELECT的结果中除掉右边SELECT的结果。三个或更多SELECT复合时,它们从左至右结合。
UPDATE
sql-statement ::= | UPDATE [ OR conflict-algorithm ] [database-name .] table-name SET assignment [, assignment]* [WHERE expr] |
assignment ::= | column-name = expr |
UPDATE语句用于改变表中所选行的字段值。每个UPDATE的赋值的等号左边为字段名而右边为任意表达式。表达式可以使用其它字段的值。所有的表达式将在赋值之前求出结果。可以使用WHERE子句限定需要改变的行。
在使用这一命令时,利用可选的ON CONFLICT子句可以定义替代的约束冲突判定算法。更多信息,参见 ON CONFLICT。
REPLACE
sql-statement ::= | REPLACE INTO [database-name .] table-name [( column-list )] VALUES ( value-list ) | REPLACE INTO [database-name .] table-name [( column-list )] select-statement |
REPLACE命令用于替代INSERT的"INSERT OR REPLACE"变体,以更好的兼容MySQL。查看 INSERT命令文档获取更多信息。
INSERT
sql-statement ::= | INSERT [OR conflict-algorithm] INTO [database-name .] table-name [(column-list)]VALUES(value-list) | INSERT [OR conflict-algorithm] INTO [database-name .] table-name [(column-list)]select-statement |
INSERT语句有两种基本形式。一种带有"VALUES"关键字,在已有表中插入一个新的行。若不定义字段列表,那么值的数目将与表中的字段数目相同。否则值的数目须与字段列表中的字段数目相同。不在字段列表中的字段被赋予缺省值或NULL(当未定义缺省值)。
INSERT的第二种形式从SELECT语句中获取数据。若未定义字段列表,则从SELECT得到的字段的数目必须与表中的字段数目相同,否则应与定义的字段列表中的字段数目相同。SELECT的每一行结果在表中插入一个新的条目。SELECT可以是简单的或者复合的。如果SELECT语句带有ORDER BY子句,ORDER BY会被忽略。
在使用这一命令时,利用可选的ON CONFLICT子句可以定义替代的约束冲突判定算法。更多信息,参见 ON CONFLICT 。为了兼容MySQL,可以使用REPLACE代替"INSERT OR REPLACE".
DELETE
sql-statement ::= | DELETE FROM [database-name .] table-name [WHERE expr] |
DELETE命令用于从表中删除记录。命令包含"DELETE FROM"关键字以及需要删除的记录所在的表名。
若不使用WHERE子句,表中的所有行将全部被删除。否则仅删除符合条件的行。
表达式
expr ::= | expr binary-op expr | expr [NOT] like-op expr [ESCAPE expr] | unary-op expr | ( expr ) | column-name | table-name . column-name | database-name . table-name . column-name | literal-value | parameter | function-name ( expr-list | * ) | expr ISNULL | expr NOTNULL | expr [NOT] BETWEEN expr AND expr | expr [NOT] IN ( value-list ) | expr [NOT] IN ( select-statement ) | expr [NOT] IN [database-name .] table-name | [EXISTS] ( select-statement ) | CASE [expr] ( WHEN expr THEN expr )+ [ELSE expr] END | CAST ( expr AS type ) |
like-op ::= | LIKE | GLOB | REGEXP |
这一节与其它的各节有所不同。我们讨论的不是一个单一的SQL命令,而是作为其他大部分命令的一部分的表达式。
SQLite支持如下的二元运算符,按优先级由高至低排列:
|| * / % + - << >> & | < <= > >= = == != <> IN AND OR
所支持的一元运算符:
- + ! ~
注意等号和“不等”号的两个变种。等号可以是 =或==. “不等”号可以是!=或<>. ||为“连接符”——它将两个字符串连接起来。 %输出左边部分以右边部分为模取模得到的余数。
二元运算符的结果均为数字,除了||连接符,它给出字符串结果。
文本值(literal value)是一个整数或浮点数。可以使用科学计数法。"."符号总是被当作小数点即使本地设定中用","来表示小数点 ——用","表示小数点会造成歧义。字符串常量由字符串加单引号(')构成。字符串内部的单引号可像Pascal 中一样用两个单引号来表示。C风格的加反斜线的表示法由于不是标准SQL而不被支持。 BLOB文本是以"x"或"X"开头的含有十六进制文本信息的文本值 For example:
X'53514697465'
文本值同样可以为"NULL".
表达式中插入文本值占位符的参数可以使用 sqlite3_bind API函数在运行时插入。参数可以是如下几种形式:
?NNN 问号跟随数字NNN为第NNN个参数占位。NNN需介于1和999之间。 ? 不加数字的问号为下一个参数占位。 :AAAA 冒号带一个标识符名称为一个名为AAAA的参数占位。命名的参数同样可以使用序号占位,被赋予的参数序号为下一个尚未被使用的序号。建议不要混合使用命名代表的参数和序号代表的参数以免引起混淆。 $AAAA $符号带一个标识符名称也可以为一个名为AAAA的参数占位。在这一情况下标识符名称可以包括一个或更多的"::" 以及包含任何文本的"(...)"后缀。该语法是Tcl编程语言中的一个可变形式。
不使用sqlite3_bind赋值的参数被视为NULL.
LIKE运算符进行模式匹配比较。运算符右边为进行匹配的模式而左边为需进行匹配的字符串。 模式中的百分号%匹配结果中的零或任意多个字符。下划线 _匹配任意单个字符。其他的任意字符匹配本身或等同的大/小写字符。 (即不区分大小写的匹配)。 (一个bug: SQLite仅对7-bit拉丁字符支持不区分大小写匹配。这是由于 LIKE运算符对8-bit iso8859字符或UTF-8字符是大小写敏感的。例如,表达式'a' LIKE 'A' 的值为真而'?' LIKE '?'为假)。
如果使用可选的ESCAPE子句,则跟随ESCAPE关键字的必须是一个有一个字符的字符串。这一字符(逃逸字符)可用于LIKE模式中,以代替百分号或下划线。逃逸字符后跟百分号,下划线或它本身代表字符串中的百分号,下划线或逃逸字符。插入的LIKE运算符功能通过调用用户函数 like(X,Y)来实现。
当使用可选的ESCAPE子句,它对函数给出第三个参数,LIKE的功能可以通过重载SQL函数like()进行改变。
GLOB运算符与LIKE相似,但它使用Unix文件 globbing 语法作为通配符。还有一点不同是GLOB对大小写敏感。 GLOB和LIKE都可以前缀NOT关键字构成相反的意思。插入的GLOB运算符功能通过调用用户函数 glob(X,Y) 可以通过重载函数改变GLOB的功能。
REGEXP运算符是用户函数regexp()的一个特殊的代表符号。缺省情况下regexp()函数不被定义,所以使用REGEXP运算符会报错。当运行时存在用户定义的"regexp"函数的定义,则调用该函数以实现REGEXP运算符功能。
字段名可以是CREATE TABLE语句定义的任何名字或如下几个特殊标识符之一"ROWID", "OID", 以及"_ROWID_".这些特殊标识符均代表每个表每一行关联的那个唯一随机整数键("row key")。仅仅在CREATE TABLE语句没有对这些特殊标识符的真实字段予以定义的情况下,它们才代表"row key"。它们与只读字段类似,可以像任何正常字段一样使用,除了在UPDATE或INSERT语句中(即是说你不能添加或更改row key)。 "SELECT * ..."不返回row key.
SELECT语句可以在表达式中出现,作为IN运算符的右边运算量,作为一个纯量,或作为EXISTS运算符的运算量。当作纯量或IN的运算量时,SELECT语句的结果仅允许有一个字段,可以使用复合的SELECT(用UNION或 EXCEPT等关键字连接)。作为EXISTS运算符的运算量时,SELECT结果中的字段被忽略,在结果为空时表达式为假,反之为真。若SELECT表达式代表的查询中不含有引用值的部分,则它将在处理其它事务之前被计算,并且结果在必要时会被重复使用。若SELECT表达式含从其它查询中得到的变量,在每一次使用时该表达式均被重新计算。
当SELECT作为IN运算符的右运算量,在左边的运算量是SELECT产生的任意一个值时,表达式返回TRUE。IN运算符前可以加NOT 构成相反的意思。
当SELECT与表达式一同出现且不在IN的右边,则SELECT结果的第一行作为表达式中使用的值。SELECT返回的结果在第一行以后的部分被忽略。返回结果为空时SELECT语句的值为NULL.
CAST表达式将的数据类型改为声明的类型。 可以是CREATE TABLE语句字段定义部分定义的对该字段有效的任意非空数据类型。
表达式支持简单函数和聚集函数。简单函数直接从输入获得结果,可用于任何表达式中。聚集函数使用结果集中的所有行计算结果,仅用于SELECT语句中。
T下面这些函数是缺省可用的。可以使用C语言写出其它的函数然后使用sqlite3_create_function() API函数添加到数据库引擎中。
注意同时重载like()的两参数和三参数版本,否则在使用/不使用 ESCAPE子句时,LIKE运算符的实现可能使用的是不同的代码。
abs(X) | 返回参数X的绝对值。 |
coalesce(X,Y,...) | 返回第一个非空参数的副本。若所有的参数均为NULL,返回NULL。至少2个参数。 |
glob(X,Y) | 用于实现SQLite的 "X GLOB Y"语法。可使用 sqlite3_create_function() 重载该函数从而改变GLOB运算符的功能。 |
ifnull(X,Y) | 返回第一个非空参数的副本。 若两个参数均为NULL,返回NULL。与上面的coalesce()类似。 |
last_insert_rowid() | 返回当前数据库连接最后插入行的ROWID。sqlite_last_insert_rowid() API函数同样可用于得到该值。 |
length(X) | 返回X的长度,以字符计。如果SQLite被配置为支持UTF-8,则返回UTF-8字符数而不是字节数。 |
like(X,Y [,Z]) | 用于实现SQL语法"X LIKE Y [ESCAPE Z]".若使用可选的ESCAPE子句,则函数被赋予三个参数,否则只有两个。可使用sqlite3_create_function() 重载该函数从而改变LIKE运算符的功能。 |
lower(X) | 返回X字符串的所有字符小写化版本。这一转换使用C语言库的tolower()函数,对UTF-8字符不能提供好的支持。 |
max(X,Y,...) | 返回最大值。参数可以不仅仅为数字,可以为字符串。大小顺序由常用的排序法则决定。注意,max()在有2个或更多参数时为简单函数,但当仅给出一个参数时它变为聚集函数。 |
min(X,Y,...) | 返回最小值。与max()类似。 |
nullif(X,Y) | 当两参数不同时返回X,否则返回NULL. |
quote(X) | 返回参数的适于插入其它SQL语句中的值。字符串会被添加单引号,在内部的引号前会加入逃逸符号。 BLOB被编码为十六进制文本。当前的VACUUM使用这一函数实现。在使用触发器实现撤销/重做功能时这一函数也很有用。 |
random(*) | 返回介于-2147483648和 +2147483647之间的随机整数。 |
round(X) round(X,Y) |
将X四舍五入,保留小数点后Y位。若忽略Y参数,则默认其为0。 |
soundex(X) | 计算字符串X的soundex编码。参数为NULL时返回字符串"?000".缺省的SQLite是不支持该函数的,当编译时选项 -DSQLITE_SOUNDEX=1 时该函数才可用。 |
sqlite_version(*) | 返回所运行的SQLite库的版本号字符串。如 "2.8.0"。 |
substr(X,Y,Z) | 返回输入字符串X中以第Y个字符开始,Z个字符长的子串。 X最左端的字符序号为1。若Y为负,则从右至左数起。若SQLite配置支持UTF-8,则“字符”代表的是UTF-8字符而非字节。 |
typeof(X) | 返回表达式X的类型。返回值可能为"null", "integer", "real", "text", 以及 "blob". SQLite的类型处理参见SQLite3的数据类型. |
upper(X) | 返回X字符串的所有字符大写化版本。这一转换使用C语言库的toupper()函数,对UTF-8字符不能提供好的支持。 |
以下是缺省可用的聚集函数列表。可以使用C语言写出其它的聚集函数然后使用sqlite3_create_function() API函数添加到数据库引擎中。
在单参数聚集函数中,参数可以加前缀DISTINCT。这时重复参数会被过滤掉,然后才穿入到函数中。例如,函数"count(distinct X)"返回字段X的不重复非空值的个数,而不是字段X的全部非空值。
avg(X) | 返回一组中非空的X的平均值。非数字值作0处理。avg()的结果总是一个浮点数,即使所有的输入变量都是整数。
|
count(X) count(*) |
返回一组中X是非空值的次数的第一种形式。第二种形式(不带参数)返回该组中的行数。 |
max(X) | 返回一组中的最大值。大小由常用排序法决定。 |
min(X) | 返回一组中最小的非空值。大小由常用排序法决定。仅在所有值为空时返回NULL。 |
sum(X) total(X) |
返回一组中所有非空值的数字和。若没有非空行,sum()返回NULL而total()返回0.0. NULL通常情况下并不是对于“没有行”的和的一个有意义的结果,但SQL标准如此要求,且大部分其它SQL数据库引擎这样定义sum(),所以SQLite 也如此定义以保证兼容。我们提供非标准的total()函数作为解决该SQL语言设计问题的一个简易方法。
total()的返回值式中为浮点数。sum()可以为整数,当所有非空输入均为整数时,和是精确的。 若sum()的任意一个输入既非整数也非NULL或计算中产生整数类型的溢出时,sum()返回接近真和的浮点数。 |