Adobe AIR 包括一个 SQL 数据库引擎,该引擎使用开放源代码 SQLite 数据库系统,支持具有许多标准 SQL 功能的本地 SQL 数据库。运行时未指定在文件系统上存储数据库数据的方式或位置。每个数据库都完全存储在单个文件中。开发人员可指定在文件系统中存储数据库文件的位置,单个 AIR 应用程序可访问一个或多个单独的数据库(即单独的数据库文件)。

本文档概述了 SQL 语法和对 Adobe AIR 本地 SQL 数据库的数据类型支持。本文档并不用作综合的 SQL 参考,而仅介绍有关 Adobe AIR 支持的 SQL 方言的详细信息。运行时支持大多数符合 SQL-92 标准的 SQL 方言。由于可以通过众多的参考资料、网站、书籍和培训材料来学习 SQL,因此本文档并不用作综合的 SQL 参考或教程。相反,本文档特别侧重于 Apollo AIR 支持的 SQL 语法,以及 SQL-92 和支持的 SQL 方言之间的差异。

本部分包含以下主题:

支持的 SQL 语法

本部分介绍 Adobe AIR SQL 数据库引擎支持的 SQL 语法。下面所列的各项分别用于说明不同的语句和子句类型、表达式、内置函数和运算符。本部分包含以下主题:

常规 SQL 语法

除了各种语句和表达式的特定语法外,以下是 SQL 语法的一般规则:

数据操作语句

数据操作语句是最常用的 SQL 语句。这些语句用于从数据库表检索、添加、修改和删除数据。支持以下数据操作语句:

SELECT

SELECT 语句用于查询数据库。SELECT 的结果是零行或多行数据,其中每行都具有固定的列数。结果中的列数由 result 列名称或 SELECT 和可选 FROM 关键字之间的表达式列表指定。

sql-statement ::= SELECT [ALL | DISTINCT] result [FROM table-list] [WHERE expr] [GROUP BY expr-list] [HAVING expr] [compound-op select-statement]* [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 )] compound-op ::= UNION | UNION ALL | INTERSECT | EXCEPT sort-expr-list ::= expr [sort-order] [, expr [sort-order]]* sort-order ::= [COLLATE collation-name] [ASC | DESC] collation-name ::= BINARY | NOCASE

任意的表达式都可用作结果。如果结果表达式是 *,则以所有表的所有列替换该表达式。如果表达式是表名后跟 .*,则结果是该表中的所有列。

DISTINCT 关键字可导致返回结果行的子集,其中每个结果行都是不同的。各个 NULL 值不被视为彼此不同。默认行为是返回所有结果行,这可通过关键字 ALL 显式指定。

对在 FROM 关键字后指定的一个或多个表执行查询。如果多个表名由逗号分隔,则查询将使用各个表的交叉联接。JOIN 语法还可用于指定如何联接表。支持的唯一一个外部联接类型是 LEFT OUTER JOINjoin-args 中的 ON 子句表达式必须解析为布尔值。括号中的子查询可用作 FROM 子句中的表。可省略整个 FROM 子句,在此情况下结果是由 result 表达式列表的值组成的单个行。

WHERE 子句用于限制查询所检索的行数。WHERE 子句表达式必须解析为布尔值。WHERE 子句筛选是在任何分组之前执行的,因此 WHERE 子句表达式不能包括聚合函数。

GROUP BY 子句导致将结果的一行或多行合并到输出的单个行中。当结果包含聚合函数时,GROUP BY 子句尤其有用。GROUP BY 子句中的表达式不必是出现在 SELECT 表达式列表中的表达式。

HAVING 子句与 WHERE 类似,因为它限制语句返回的行数。但是,HAVING 子句在发生由 GROUP BY 子句指定的任何分组后应用。因此,HAVING 表达式可能引用包括聚合函数的值。不要求 HAVING 子句表达式出现在 SELECT 列表中。与 WHERE 表达式一样,HAVING 表达式必须解析为布尔值。

ORDER BY 子句导致对输出行进行排序。ORDER BY 子句的 sort-expr-list 参数是用作排序关键字的表达式列表。对于简单的 SELECT,这些表达式不必是结果的一部分,但是在复合 SELECT(使用 compound-op 运算符之一的 SELECT)中,每个排序表达式都必须与结果列之一完全匹配。每个排序表达式可能(可选)后跟 sort-order 子句,该子句包含 COLLATE 关键字以及用于对文本进行排序的排序规则函数的名称和/或用于指定排序顺序(升序或降序)的关键字 ASCDESC。可省略 sort-order,在此情况下将使用默认值(升序)。有关 COLLATE 子句和排序规则函数的定义,请参阅 COLLATE

LIMIT 子句为结果中返回的行数设定上限。负的 LIMIT 指示无上限。LIMIT 后面的可选 OFFSET 指定要在结果集开头跳过的行数。在复合 SELECT 查询中,LIMIT 子句可能仅出现在最终 SELECT 语句之后,并且限制应用于整个查询。请注意,如果在 LIMIT 子句中使用 OFFSET 关键字,则限制是第一个整数,偏移量是第二个整数。如果使用逗号而不是 OFFSET 关键字,则偏移量是第一个数,限制是第二个数。此表面上的矛盾是有意的 — 这最大限度提高了与早期 SQL 数据库系统的兼容性。

复合 SELECT 是由运算符 UNIONUNION ALLINTERSECTEXCEPT 之一所连接的两个或更多个简单 SELECT 语句构成的。在复合 SELECT 中,所有用于构成的 SELECT 语句都必须指定相同数量的结果列。在最终 SELECT 语句之后只能有一个 ORDER BY 子句(且在单个 LIMIT 子句之前,如果指定这类子句)。UNIONUNION ALL 运算符将前面和后面的 SELECT 语句的结果组合到单个表中。两者的差异在于,在 UNION 中,所有结果行都不重复,但是在 UNION ALL 中,则可能存在重复行。INTERSECT 运算符求出前面和后面的 SELECT 语句的结果的交集。在删除后面的 SELECT 的结果后,EXCEPT 求出前面的 SELECT 的结果。将三个或更多 SELECT 语句连接为复合语句时,它们从第一个到最后一个进行组合。

有关允许的表达式的定义,请参阅表达式

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 REPLACE INTO [database-name.] table-name [(column-list)] VALUES (value-list) | REPLACE INTO [database-name.] table-name [(column-list)] select-statement

第一种形式(使用 VALUES 关键字)在现有表中创建单个新行。如果未指定 column-list,则值的数量必须等于表中的列数。如果指定了 column-list,则值的数量必须与指定列的数量匹配。将用创建表时定义的默认值填充未出现在列的列表中的表列;如果未定义默认值,则使用 NULL 填充。

INSERT 语句的第二种形式从 SELECT 语句提取其数据。如果未指定 column-list,则 SELECT 的结果中的列数必须与表中的列数完全匹配,或者它必须与在 column-list 中指定的列数完全匹配。在表中为 SELECT 结果的每一行创建一个新项。SELECT 可能是简单的或复合的。有关允许的 SELECT 语句的定义,请参阅 SELECT

可选的 conflict-algorithm 允许指定要在此命令过程中使用的替代约束冲突解决算法。有关冲突算法的说明和定义,请参阅 ON CONFLICT(冲突算法)

该语句的两种 REPLACE INTO 形式等效于将标准的 INSERT [OR conflict-algorithm] 形式与 REPLACE 冲突算法一起使用(即 INSERT OR REPLACE... 形式)。

UPDATE

UPDATE 语句用于更改表的一组行中的列值。

sql-statement ::= UPDATE [OR conflict-algorithm] [database-name.] table-name SET assignment [, assignment]* [WHERE expr] conflict-algorithm ::= ROLLBACK | ABORT | FAIL | IGNORE | REPLACE assignment ::= column-name = expr

UPDATE 中的每个赋值都指定等号左侧的列名和右侧的任意表达式。表达式可能使用其他列的值。所有表达式都是在进行任何赋值之前计算的。有关允许的表达式的定义,请参阅表达式

WHERE 子句用于限制所更新的行。WHERE 子句表达式必须解析为布尔值。

可选的 conflict-algorithm 允许指定要在此命令过程中使用的替代约束冲突解决算法。有关冲突算法的说明和定义,请参阅 ON CONFLICT(冲突算法)

DELETE

delete 命令用于从表中删除记录。

sql-statement ::= DELETE FROM [database-name.] table-name [WHERE expr]

该命令由 DELETE FROM 关键字后跟要从其删除记录的表的名称组成。

如果没有 WHERE 子句,则删除表的所有行。如果提供了 WHERE 子句,则仅删除与表达式匹配的那些行。WHERE 子句表达式必须解析为布尔值。有关允许的表达式的定义,请参阅表达式

数据定义语句

数据定义语句用于创建、修改和删除数据库对象,如表、视图、索引和触发器。支持以下数据定义语句:

CREATE TABLE

CREATE TABLE 语句由关键字 CREATE TABLE 后跟新表的名称以及列定义和约束的列表(在括号中)组成。表名可以是标识符或字符串。

sql-statement ::= CREATE [TEMP | TEMPORARY] TABLE [IF NOT EXISTS] [database-name.] table-name ( column-def [, column-def]* [, constraint]* ) sql-statement ::= CREATE [TEMP | TEMPORARY] TABLE [database-name.] table-name AS select-statement column-def ::= name [type] [[CONSTRAINT name] column-constraint]* type ::= typename | typename ( number ) | typename ( number , number ) column-constraint ::= NOT NULL [ conflict-clause ] | PRIMARY KEY [sort-order] [ conflict-clause ] [AUTOINCREMENT] | UNIQUE [conflict-clause] | CHECK ( expr ) | DEFAULT default-value | COLLATE collation-name constraint ::= PRIMARY KEY ( column-list ) [conflict-clause] | UNIQUE ( column-list ) [conflict-clause] | CHECK ( expr ) conflict-clause ::= ON CONFLICT conflict-algorithm conflict-algorithm ::= ROLLBACK | ABORT | FAIL | IGNORE | REPLACE default-value ::= NULL | string | number | CURRENT_TIME | CURRENT_DATE | CURRENT_TIMESTAMP sort-order ::= ASC | DESC collation-name ::= BINARY | NOCASE column-list ::= column-name [, column-name]*

每个列定义都是列的名称后跟该列的数据类型,然后是一个或多个可选的列约束。列的数据类型限制可在该列中存储的数据。如果尝试在具有不同数据类型的列中存储某个值,则运行时会将该值转换为相应的类型(如果可能),或者引发错误。有关其他信息,请参阅数据类型支持部分。

NOT NULL 列约束指示列不能包含 NULL 值。

UNIQUE 约束导致在指定的一个或多个列上创建索引。此索引必须包含唯一键 — 没有两行可能包含重复值或者指定的一个或多个列的值的组合。CREATE TABLE 语句可具有多个 UNIQUE 约束(包括列定义中有 UNIQUE 约束的多个列)和/或多个表级 UNIQUE 约束。

CHECK 约束定义计算结果必须为 true 的表达式,以便插入或更新行的数据。CHECK 表达式必须解析为布尔值。

列定义中的 COLLATE 子句指定在比较列的文本项时要使用的文本排序规则函数。默认情况下,使用 BINARY 排序规则函数。有关 COLLATE 子句和排序规则函数的详细信息,请参阅 COLLATE

DEFAULT 约束指定执行 INSERT 时要使用的默认值。该值可能是 NULL、字符串常数或数字。默认值还可能是与大小写无关的特殊关键字 CURRENT_TIMECURRENT_DATECURRENT_TIMESTAMP 之一。如果该值是 NULL、字符串常数或数字,则只要 INSERT 语句不指定列的值,则按字面将它插入到列中。如果该值是 CURRENT_TIMECURRENT_DATECURRENT_TIMESTAMP,则将当前的 UTC 日期和/或时间插入到列中。对于 CURRENT_TIME,格式为 HH:MM:SS。对于 CURRENT_DATE,格式为 YYYY-MM-DDCURRENT_TIMESTAMP 的格式为 YYYY-MM-DD HH:MM:SS

指定 PRIMARY KEY 通常仅在对应的一个或多个列上创建 UNIQUE 索引。但是,如果 PRIMARY KEY 约束在具有数据类型 INTEGER 的单个列上,则该列将在内部用作表的实际主键。这意味着该列只能保存唯一整数值。如果表没有 INTEGER PRIMARY KEY 列,则在插入行时将自动生成整数键。使用特殊名称 ROWIDOID_ROWID_ 之一,始终可以访问行的主键。可使用这些名称,而不管它是显式声明的 INTEGER PRIMARY KEY 还是内部生成的值。INTEGER PRIMARY KEY 列还可包括关键字 AUTOINCREMENT。如果使用 AUTOINCREMENT 关键字,则在执行 INSERT 语句时,数据库会在 INTEGER PRIMARY KEY 列中自动生成并插入顺序递增的整数键。

CREATE TABLE 语句中只能有一个 PRIMARY KEY 约束。它可以是一个列的定义的一部分或一个单表级 PRIMARY KEY 约束。主键列隐式为 NOT NULL

许多约束后面的可选 conflict-clause 允许为该约束指定替代的默认约束冲突解决算法。默认值为 ABORT。同一表中的不同约束可能具有不同的默认冲突解决算法。如果 INSERTUPDATE 语句指定不同的冲突解决算法,则使用该算法,替代在 CREATE TABLE 语句中指定的算法。有关其他信息,请参阅 ON CONFLICT(冲突算法)部分。

其他约束(如 FOREIGN KEY 约束)不会导致错误,但运行时会忽略它们。

如果在 CREATETABLE 之间出现 TEMPTEMPORARY 关键字,则创建的表仅在同一数据库连接(SQLConnection 实例)内才是可见的。关闭数据库连接时会自动删除它。在临时表上创建的任何索引也是临时的。临时的表和索引存储在与主数据库文件不同的单独文件中。

如果指定可选的 database-name 前缀,则在指定的数据库(通过使用指定的数据库名称调用 attach() 方法连接到 SQLConnection 实例的数据库)中创建表。除非 database-name 前缀是 temp,否则同时指定 database-name 前缀和 TEMP 关键字是错误的。如果未指定数据库名称,而且不存在 TEMP 关键字,则在主数据库(使用 open()openAsync() 方法连接到 SQLConnection 实例的数据库)中创建表。

对表中的列数或约束数没有任何限制。对行中的数据量也没有任何限制。

CREATE TABLE AS 形式将表定义为查询的结果集。表列的名称是结果中列的名称。

如果存在可选的 IF NOT EXISTS 子句,而且同名的其他表已存在,则数据库将忽略 CREATE TABLE 命令。

可使用 DROP TABLE 语句删除表,并可使用 ALTER TABLE 语句进行有限的更改。

ALTER TABLE

ALTER TABLE 命令允许用户重命名现有表或向其添加新列。无法从表中删除列。

sql-statement ::= ALTER TABLE [database-name.] table-name alteration alteration ::= RENAME TO new-table-name alteration ::= ADD [COLUMN] column-def

RENAME TO 语法用于将由 [database-name.] table-name 标识的表重命名为 new-table-name。此命令不能用于在附加的数据库之间移动表,而只能用于重命名同一数据库中的表。

如果要重命名的表具有触发器或索引,则在重命名表后,这些触发器或索引仍然附加到表。但是,如果存在任何视图定义或由引用要重命名的表的触发器执行的语句,则不会自动修改它们以使用新表名。如果重命名的表具有关联的视图或触发器,则必须手动删除再重新创建使用新表名的触发器或视图定义。

ADD [COLUMN] 语法用于向现有表添加新列。新列始终追加到现有列的列表的结尾。column-def 子句可采用 CREATE TABLE 语句中允许的任何形式,但有以下限制:

ALTER TABLE 语句的执行时间不受表中数据量的影响。

DROP TABLE

DROP TABLE 语句删除使用 CREATE TABLE 语句添加的表。具有指定 table-name 的表就是所删除的表。它将从数据库和磁盘文件中完全删除。无法恢复表。与表关联的所有索引也将被删除。

sql-statement ::= DROP TABLE [IF EXISTS] [database-name.] table-name

默认情况下,DROP TABLE 语句不减小数据库文件的大小。将保留数据库中的空白空间,并在后续 INSERT 操作中使用。若要删除数据库中的可用空间,请使用 SQLConnection.clean() 方法。如果在最初创建数据库时 autoClean 参数设置为 true,则将自动释放空间。

可选的 IF EXISTS 子句抑制表不存在时通常会导致的错误。

CREATE INDEX

CREATE INDEX 命令包含关键字 CREATE INDEX,后跟新索引的名称、关键字 ON、之前创建的要编制索引的表的名称,以及表中其值用于索引键的列的名称的带括号列表。

sql-statement ::= CREATE [UNIQUE] INDEX [IF NOT EXISTS] [database-name.] index-name ON table-name ( column-name [, column-name]* ) column-name ::= name [COLLATE collation-name] [ASC | DESC]

每个列名都可后跟 ASCDESC 关键字以指示排序顺序,但运行时会忽略指定的排序顺序。排序始终按升序执行。

每个列名后面的 COLLATE 子句定义用于该列中文本值的排序规则序列。默认的排序规则序列是在 CREATE TABLE 语句中为该列定义的排序规则序列。如果未指定排序规则序列,则使用 BINARY 排序规则序列。有关 COLLATE 子句和排序规则函数的定义,请参阅 COLLATE

对于可附加到单个表的索引数没有任何限制。对于索引中的列数也没有限制。

DROP INDEX

drop index 语句删除使用 CREATE INDEX 语句添加的语句。指定的索引将从数据库文件中完全删除。恢复索引的唯一方法是,重新输入相应的 CREATE INDEX 命令。

sql-statement ::= DROP INDEX [IF EXISTS] [database-name.] index-name

默认情况下,DROP INDEX 语句不减小数据库文件的大小。将保留数据库中的空白空间,并在后续 INSERT 操作中使用。若要删除数据库中的可用空间,请使用 SQLConnection.clean() 方法。如果在最初创建数据库时 autoClean 参数设置为 true,则将自动释放空间。

CREATE VIEW

CREATE VIEW 命令为预定义的 SELECT 语句分配一个名称。此新名称然后可在其他 SELECT 语句的 FROM 子句中使用以代替表名。视图通常用于简化查询,方法是将一组复杂的(和频繁使用的)数据组合到可在其他操作中使用的结构中。

sql-statement ::= CREATE [TEMP | TEMPORARY] VIEW [IF NOT EXISTS] [database-name.] view-name AS select-statement

如果在 CREATEVIEW 之间出现 TEMPTEMPORARY 关键字,则创建的视图仅对已打开数据库的 SQLConnection 实例是可见的,并且在关闭数据库时会自动删除该视图。

如果指定了 [database-name],则使用指定的 name 参数在指定的数据库(使用 attach() 方法连接到 SQLConnection 实例的数据库)中创建视图。除非 [database-name]temp,否则同时指定 [database-name]TEMP 关键字是错误的。如果未指定数据库名称,而且不存在 TEMP 关键字,则在主数据库(使用 open()openAsync() 方法连接到 SQLConnection 实例的数据库)中创建视图。

视图是只读的。除非至少定义一个关联类型(INSTEAD OF DELETEINSTEAD OF INSERTINSTEAD OF UPDATE)的触发器,否则不能对视图使用 DELETEINSERTUPDATE 语句。有关为视图创建触发器的信息,请参阅 CREATE TRIGGER

使用 DROP VIEW 语句可从数据库中删除视图。

DROP VIEW

DROP VIEW 语句删除由 CREATE VIEW 语句创建的视图。

sql-statement ::= DROP VIEW [IF EXISTS] view-name

指定的 view-name 是要删除的视图的名称。将从数据库中删除它,但不会修改基础表中的数据。

CREATE TRIGGER

create trigger 语句用于向数据库架构添加触发器。触发器是在发生指定的数据库事件 (database-event) 时自动执行的数据库操作 (trigger-action)。

sql-statement ::= CREATE [TEMP | TEMPORARY] TRIGGER [IF NOT EXISTS] [database-name.] trigger-name [BEFORE | AFTER] database-event ON table-name trigger-action sql-statement ::= CREATE [TEMP | TEMPORARY] TRIGGER [IF NOT EXISTS] [database-name.] trigger-name INSTEAD OF database-event ON view-name trigger-action database-event ::= DELETE | INSERT | UPDATE | UPDATE OF column-list trigger-action ::= [FOR EACH ROW] [WHEN expr] BEGIN trigger-step ; [ trigger-step ; ]* END trigger-step ::= update-statement | insert-statement | delete-statement | select-statement column-list ::= column-name [, column-name]*

触发器被指定为只要出现以下条件就会激发:发生特定数据库表的 DELETEINSERTUPDATE,或者表的一个或多个指定列的 UPDATE 被更新。除非使用了 TEMPTEMPORARY 关键字,否则触发器是永久性的。在这种情况下,当关闭 SQLConnection 实例的主数据库连接时,将删除触发器。如果未指定时间(BEFOREAFTER),则触发器默认为 BEFORE

仅支持 FOR EACH ROW 触发器,因此 FOR EACH ROW 文本是可选的。对于 FOR EACH ROW 触发器,如果 WHEN 子句表达式的计算结果为 true,则对导致触发器激发的语句所插入、更新或删除的每个数据库行执行 trigger-step 语句。

如果提供了 WHEN 子句,则仅对 WHEN 子句为 true 的行执行指定为触发器步骤的 SQL 语句。如果未提供 WHEN 子句,则对所有行执行 SQL 语句。

在触发器体(trigger-action 子句)中,受影响表的更改之前值和更改之后值使用特殊的表名 OLDNEW 提供。OLDNEW 表的结构与创建触发器的表的结构匹配。OLD 表包含由触发语句修改或删除的任何行,处于其在触发语句操作之前的状态。NEW 表包含由触发语句修改或创建的任何行,处于其在触发语句操作之后的状态。WHEN 子句和 trigger-step 语句都可访问使用 NEW.column-nameOLD.column-name 形式的引用插入、删除或更新的行的值,其中 column-name 是与触发器关联的表中的列的名称。OLDNEW 表引用的可用性取决于触发器所处理的 database-event 类型:

指定的时间(BEFOREAFTERINSTEAD OF)确定何时执行与插入、修改或删除关联行有关的 trigger-step 语句。可将 ON CONFLICT 子句指定为 trigger-stepUPDATEINSERT 语句的一部分。但是,如果将 ON CONFLICT 子句指定为导致触发器激发的语句的一部分,则改用该冲突处理策略。

除了表触发器外,还可在视图上创建 INSTEAD OF 触发器。如果在某个视图上定义了一个或多个 INSTEAD OF INSERTINSTEAD OF DELETEINSTEAD OF UPDATE 触发器,则不将在该视图上执行关联类型的语句(INSERTDELETEUPDATE)视为错误。在这种情况下,在视图上执行 INSERTDELETEUPDATE 会导致关联触发器激发。由于触发器是 INSTEAD OF 触发器,因此导致触发器激发的语句不会修改视图的基础表。但是,触发器可用于对基础表执行修改操作。

在具有 INTEGER PRIMARY KEY 列的表上创建触发器时,请牢记一个重要问题。如果 BEFORE 触发器修改要由导致触发器激发的语句更新的行的 INTEGER PRIMARY KEY 列,则不会发生更新。解决方法是创建具有 PRIMARY KEY 列而不是 INTEGER PRIMARY KEY 列的表。

可使用 DROP TRIGGER 语句删除触发器。删除表或视图时,也会自动删除与该表或视图关联的所有触发器。

RAISE() 函数

特殊的 SQL 函数 RAISE() 可在触发器的 trigger-step 语句中使用。此函数的语法如下:

raise-function ::= RAISE ( ABORT, error-message ) | RAISE ( FAIL, error-message ) | RAISE ( ROLLBACK, error-message ) | RAISE ( IGNORE )

在触发器执行期间调用前三种形式之一时,会执行指定的 ON CONFLICT 处理操作(ABORTFAILROLLBACK),而且当前语句的执行结束。ROLLBACK 被认为是语句执行失败,因此执行其 execute() 方法的 SQLStatement 实例将调度 error (SQLErrorEvent.ERROR) 事件。被调度的事件对象的 error 属性中的 SQLError 对象将其 details 属性设置为在 RAISE() 函数中指定的 error-message

调用 RAISE(IGNORE) 时,将放弃当前触发器的剩余部分、导致触发器执行的语句和执行的任何后续触发器。不回滚数据库更改。如果导致触发器执行的语句本身是触发器的一部分,则在下一步开始时该触发器程序将继续执行。有关冲突解决算法的详细信息,请参阅 ON CONFLICT(冲突算法)部分。

DROP TRIGGER

DROP TRIGGER 语句删除由 CREATE TRIGGER 语句创建的触发器。

sql-statement ::= DROP TRIGGER [IF EXISTS] [database-name.] trigger-name

将从数据库中删除触发器。请注意,在删除其关联表时,会自动删除触发器。

特殊的语句和子句

本部分介绍几个对运行时提供的 SQL 进行扩展的子句,以及可在许多语句、注释和表达式中使用的两个语言元素。本部分中的元素如下:

COLLATE

COLLATE 子句在 SELECTCREATE TABLECREATE INDEX 语句中使用,指定对值进行比较或排序时使用的比较算法。

sql-statement ::= COLLATE collation-name collation-name ::= BINARY | NOCASE

列的默认排序规则类型是 BINARY。将 BINARY 排序规则用于 TEXT 存储类的值时,通过比较内存中表示值的字节来执行二进制排序规则,而不管文本编码如何。

NOCASE 排序规则序列仅适用于 TEXT 存储类的值。在使用时,NOCASE 排序规则执行不区分大小写的比较。

排序规则序列不用于 NULLBLOBINTEGERREAL 类型的存储类。

若要将除 BINARY 之外的排序规则类型用于列,必须将 COLLATE 子句指定为 CREATE TABLE 语句中列定义的一部分。每当对两个 TEXT 值进行比较时,都将按照以下规则使用排序规则序列来确定比较的结果:

EXPLAIN

EXPLAIN 命令修饰符是 SQL 的非标准扩展。

sql-statement ::= EXPLAIN sql-statement

如果 EXPLAIN 关键字出现在任何其他 SQL 语句之前,则结果报告它用于执行命令的虚拟机指令序列,而不是实际执行命令,就像不存在 EXPLAIN 关键字一样。EXPLAIN 功能是一种高级功能,允许开发人员更改 SQL 语句文本以尝试优化性能或调试看起来工作不正常的语句。

ON CONFLICT(冲突算法)

ON CONFLICT 子句不是单独的 SQL 命令。它是可出现在许多其他 SQL 命令中的非标准子句。

conflict-clause ::= ON CONFLICT conflict-algorithm conflict-clause ::= OR conflict-algorithm conflict-algorithm ::= ROLLBACK | ABORT | FAIL | IGNORE | REPLACE

ON CONFLICT 子句的第一种形式(使用关键字 ON CONFLICT)在 CREATE TABLE 语句中使用。对于 INSERTUPDATE 语句,使用第二种形式(将 ON CONFLICT 替换为 OR)以使语法看起来更自然。例如,语句变为 INSERT OR IGNORE,而不是 INSERT ON CONFLICT IGNORE。虽然关键字是不同的,但是子句的含义在任一形式中都是相同的。

ON CONFLICT 子句指定用于解决约束冲突的算法。五种算法为 ROLLBACKABORTFAILIGNOREREPLACE。默认算法为 ABORT。以下是对这五种冲突算法的说明:

INSERTUPDATE 语句的 OR 子句中指定的算法将覆盖在 CREATE TABLE 语句中指定的任何算法。如果未在 CREATE TABLE 语句或者执行 INSERTUPDATE 语句中指定算法,则将使用 ABORT 算法。

REINDEX

REINDEX 命令用于删除并重新创建一个或多个索引。在排序规则序列的定义更改时,此命令很有用。

sql-statement ::= REINDEX collation-name sql-statement ::= REINDEX [database-name .] ( table-name | index-name )

在第一种形式中,将重新创建使用指定排序规则序列的所有附加数据库中的所有索引。在第二种形式中,指定 table-name 时,将重新生成与表关联的所有索引。如果提供了 index-name,则仅删除并重新创建指定的索引。

注释

注释不是 SQL 命令,但它们可出现在 SQL 查询中。运行时将它们视为空白。它们可从能找到空白的任何位置开始,包括跨多行的表达式的内部。

comment ::= single-line-comment | block-comment single-line-comment ::= -- single-line block-comment ::= /* multiple-lines or block [*/]

单行注释由两个短划线指示。单行注释仅扩展到当前行的结尾。

块注释可跨任何数目的行,或者嵌入到单行中。如果没有终止分隔符,则块注释可扩展到输入的结尾。此情况并不被视为错误。新的 SQL 语句可在块注释结束后的行上开始。块注释可嵌入到能出现空白的任何位置中,包括表达式内部和其他 SQL 语句的中间。块注释不嵌套。忽略块注释内的单行注释。

表达式

表达式是其他 SQL 块中的子命令。以下介绍 SQL 语句中表达式的有效语法:

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 ) | expr COLLATE collation-name like-op ::= LIKE | GLOB binary-op ::= see Operators unary-op ::= see Operators parameter ::= :param-name | @param-name | ? value-list ::= literal-value [, literal-value]* literal-value ::= literal-string | literal-number | literal-boolean | literal-blob | literal-null literal-string ::= 'string value' literal-number ::= integer | number literal-boolean ::= true | false literal-blob ::= X'string of hexadecimal data' literal-null ::= NULL

表达式是值和可解析为单个值的运算符的任何组合。根据表达式解析为布尔值(true 或 false)还是解析为非布尔值,可将表达式分为两种常规类型。

在几种常见情况下,包括在 WHERE 子句、HAVING 子句、JOIN 子句中的 ON 表达式以及 CHECK 表达式中,表达式必须解析为布尔值。以下类型的表达式满足此条件:

字面值

文本数字值是以整数或浮点数形式书写的。支持科学记数法。.(句点)字符始终用作小数点。

字符串文本是通过用单引号 ' 将字符串括起来指示的。若要将单引号包括在字符串中,请连续放置两个单引号,例如:''

布尔文本由值 truefalse 指示。文本布尔值用于 Boolean 列数据类型。

BLOB 文本是包含十六进制数据且前面有单个 xX 字符的字符串文本,如 X'53514697465'

字面值也可以是标记 NULL

列名

列名可以是在 CREATE TABLE 语句中定义的任何名称或以下特殊标识符之一:ROWIDOID_ROWID_。这些特殊标识符都描述与每个表的每一行关联的唯一随机整数键(“行键”)。如果 CREATE TABLE 语句未定义同名的真正列,则特殊标识符仅引用行键。行键充当只读列。行键可在能使用常规列的任何位置使用,但您不能在 UPDATEINSERT 语句中更改行键的值。SELECT * FROM table 语句在其结果集中不包括行键。

SELECT 语句

SELECT 语句可在表达式中作为 IN 运算符的右操作数,作为纯量(单个结果值)或者作为 EXISTS 运算符的操作数。用作纯量或 IN 运算符的操作数时,SELECT 在其结果中只能具有单个列。允许使用复合 SELECT 语句(通过诸如 UNIONEXCEPT 之类的关键字连接)。在使用 EXISTS 运算符时,忽略 SELECT 的结果集中的列。如果存在一个或多个行,则表达式返回 TRUE;如果结果集为空,则返回 FALSE。如果 SELECT 表达式中没有项引用包含查询中的值,则该表达式将在任何其他处理之前计算一次,并在必要时重用结果。如果 SELECT 表达式不包含外部查询(称为相关子查询)中的变量,则 SELECT 在每次需要时都重新进行计算。

SELECTIN 运算符的右操作数时,如果左操作数的结果等于 SELECT 语句结果集中的任一值,则 IN 运算符返回 TRUE。可在 IN 运算符前面加上 NOT 关键字以反转测试的意义。

如果 SELECT 出现在表达式内但不是 IN 运算符的右操作数,则 SELECT 结果的第一行将成为表达式中使用的值。如果 SELECT 生成多个结果行,则忽略第一行后的所有行。如果 SELECT 未生成行,则 SELECT 的值为 NULL

CAST 表达式

CAST 表达式将指定的值的数据类型更改为提供的类型。指定的类型可以是对 CREATE TABLE 语句的列定义中的类型有效的任何非空类型名称。有关详细信息,请参阅数据类型支持

其他表达式元素

这些部分介绍可在表达式中使用的其他 SQL 元素:

内置函数

内置函数分为以下三种主要类别:

除了这些函数外,还有一个用于提供执行触发器时的错误通知的特殊函数 RAISE()。此函数只能在 CREATE TRIGGER 语句体使用。有关 RAISE() 函数的信息,请参阅 CREATE TRIGGER > RAISE()

与 SQL 中的所有关键字一样,函数名称不区分大小写。

聚合函数

聚合函数对多行中的值执行操作。这些函数主要在 SELECT 语句中与 GROUP BY 子句一起使用。

AVG(X) 返回一个组中所有非 NULL X 的平均值。看起来不像数字的字符串和 BLOB 值被解释为 0。AVG() 的结果始终是浮点值,即使所有输入都是整数。

COUNT(X)

COUNT(*)

第一种形式返回 X 在组中不是 NULL 的次数的计数。第二种形式(使用 * 参数)返回组中的总行数。
MAX(X) 返回组中所有值的最大值。通常的排序顺序用于确定最大值。
MIN(X) 返回组中所有值的最小非 NULL 值。通常的排序顺序用于确定最小值。如果组中的所有值都是 NULL,则返回 NULL

SUM(X)

TOTAL(X)

返回组中所有非 NULL 值的数字和。如果所有值都是 NULL,则 SUM() 返回 NULLTOTAL() 返回 0.0TOTAL() 的结果始终是浮点值。如果所有非 NULL 输入都是整数,则 SUM() 的结果是整数值。如果 SUM() 的任一输入不是整数且不是 NULL,则 SUM() 返回浮点值。此值可能是真实和的近似值。

在采用单个参数的上述任一聚合函数中,可在该参数前面加上关键字 DISTINCT。在这种情况下,在将重复的元素传递到聚合函数之前,会对其进行筛选。例如,函数调用 COUNT(DISTINCT x) 返回列 X 的非重复值数目,而不是列 x 中非 NULL 值的总数。

标量函数

标量函数一次对一行上的值进行运算。以下是这些函数的列表:

ABS(X) 返回参数 X 的绝对值。
COALESCE(X, Y, ...) 返回第一个非 NULL 参数的副本。如果所有参数都为 NULL,则返回 NULL。必须至少有两个参数。
GLOB(X, Y) 此函数用于实现 X GLOB Y 语法。
IFNULL(X, Y) 返回第一个非 NULL 参数的副本。如果两个参数都为 NULL,则返回 NULL。此函数的行为与 COALESCE() 相同。
HEX(X) 该参数被解释为 BLOB 存储类型的值。结果是该值内容的十六进制呈现。
LAST_INSERT_ROWID() 返回通过当前的 SQLConnection 插入到数据库的最后一行的行标识符(生成的主键)。此值与 SQLConnection.lastInsertRowID 属性返回的值相同。
LENGTH(X) 返回 X 的字符串长度(以字符计)。
LIKE(X, Y [, Z]) 此函数用于实现 SQL 的 X LIKE Y [ESCAPE Z] 语法。如果存在可选的 ESCAPE 子句,则使用三个参数调用该函数。否则,仅使用两个参数调用它。
LOWER(X) 返回字符串 X 的副本,其中所有字符都已转换为小写形式。

LTRIM(X)

LTRIM(X, Y)

返回通过删除 X 左侧的空格而形成的字符串。如果指定了 Y 参数,则函数将从 X 的左侧删除 Y 中的任何字符。
MAX(X, Y, ...) 返回具有最大值的参数。除了数字外,参数可能是字符串。最大值由定义的排序顺序确定。请注意,当 MAX() 具有 2 个或更多参数时,它是简单函数,而它只有一个参数时则是聚合函数。
MIN(X, Y, ...) 返回具有最小值的参数。除了数字外,参数可能是字符串。最小值由定义的排序顺序确定。请注意,当 MIN() 具有 2 个或更多参数时,它是简单函数,而它只有一个参数时则是聚合函数。
NULLIF(X, Y) 如果参数是不同的,则返回第一个参数,否则返回 NULL
QUOTE(X) 此例程返回一个字符串,该字符串是其适合于包含到另一 SQL 语句中的参数的值。字符串括在单引号中,并根据需要对内部引号转义。BLOB 存储类作为十六进制文本进行编码。在编写触发器以实现撤消/重做功能时,此函数是很有用的。
RANDOM(*) 返回一个介于 -9223372036854775808 和 9223372036854775807 之间的伪随机整数。此随机值不是强加密的。
RANDOMBLOB(N) 返回一个包含伪随机字节的 N 字节 BLOB。N 应该是一个正整数。此随机值不是强加密的。如果 N 的值为负,则返回单个字节。

ROUND(X)

ROUND(X, Y)

将数值 X 舍入到小数点右侧的 Y 位。如果省略 Y 参数,则使用 0。

RTRIM(X)

RTRIM(X, Y)

返回通过删除 X 右侧的空格而形成的字符串。如果指定了 Y 参数,则函数将从 X 的右侧删除 Y 中的任何字符。
SUBSTR(X, Y, Z) 返回输入字符串 X 中以第 Y 个字符开始且长度为 Z 个字符的子字符串。X 的最左侧字符是索引位置 1。如果 Y 为负,则通过从右(代替从左)数来查找子字符串的第一个字符。

TRIM(X)

TRIM(X, Y)

返回一个通过从 X 的左侧和右侧删除空格而形成的字符串。如果指定了 Y 参数,则该函数将从 X 的左侧和右侧删除 Y 中的任何字符。
TYPEOF(X) 返回表达式 X 的类型。可能的返回值有“null”、“integer”、“real”、“text”和“blob”。有关数据类型的详细信息,请参阅数据类型支持
UPPER(X) 返回已转换为全大写字母的输入字符串 X 的副本。
ZEROBLOB(N) 返回包含 0x00 的 N 字节的 BLOB。

日期和时间格式函数

日期和时间格式函数是一组用于创建带格式的日期和时间数据的标量函数。请注意,这些函数对字符串值和数字值进行运算,并返回字符串值和数字值。这些函数并不预定用于 DATE 数据类型。如果对其声明数据类型为 DATE 的列中的数据使用这些函数,则它们不会像预期的那样工作。

DATE(T, ...) DATE() 函数返回一个包含日期的字符串,日期格式为:YYYY-MM-DD。第一个参数 (T) 指定在时间格式下找到的格式的时间字符串。可在时间字符串后指定任何数量的修饰符。可在修饰符下找到这些修饰符。
TIME(T, ...) TIME() 函数返回一个包含时间的字符串,时间格式为 HH:MM:SS。第一个参数 (T) 指定在时间格式下找到的格式的时间字符串。可在时间字符串后指定任何数量的修饰符。可在修饰符下找到这些修饰符。
DATETIME(T, ...) DATETIME() 函数返回一个包含日期和时间的字符串,日期和时间格式为 YYYY-MM-DD HH:MM:SS。第一个参数 (T) 指定在时间格式下找到的格式的时间字符串。可在时间字符串后指定任何数量的修饰符。可在修饰符下找到这些修饰符。
JULIANDAY(T, ...) JULIANDAY() 函数返回一个指示自公元前 4714 年 11 月 24 日中午(按格林尼治标准时间)至所提供日期的天数的数字。第一个参数 (T) 指定在时间格式下找到的格式的时间字符串。可在时间字符串后指定任何数量的修饰符。可在修饰符下找到这些修饰符。
STRFTIME(F, T, ...) STRFTIME() 例程返回根据指定为第一个参数 F 的格式字符串设置格式的日期。格式字符串支持以下替换:

%d 一月中的某天
%f 小数秒 SS.SSS
%H 小时 00-24
%j 一年中的某天 001-366
%J 罗马儒略历的日期编号
%m 月份 01-12
%M 分钟 00-59
%s 自 1970-01-01 以来的秒数
%S 秒 00-59
%w 一周中的某天 0-6(星期日 = 0)
%W 一年中的某周 00-53
%Y 年份 0000-9999
%% %

第二个参数 (T) 指定在时间格式下找到的格式的时间字符串。可在时间字符串后指定任何数量的修饰符。可在修饰符下找到这些修饰符。
时间格式

时间字符串可采用以下任一格式:

YYYY-MM-DD 2007-06-15
YYYY-MM-DD HH:MM 2007-06-15 07:30
YYYY-MM-DD HH:MM:SS 2007-06-15 07:30:59
YYYY-MM-DD HH:MM:SS.SSS 2007-06-15 07:30:59.152
YYYY-MM-DDTHH:MM 2007-06-15T07:30
YYYY-MM-DDTHH:MM:SS 2007-06-15T07:30:59
YYYY-MM-DDTHH:MM:SS.SSS 2007-06-15T07:30:59.152
HH:MM 07:30(日期是 2000-01-01)
HH:MM:SS 07:30:59(日期是 2000-01-01)
HH:MM:SS.SSS 07:30:59:152(日期是 2000-01-01)
目前 当前的日期和时间(按通用协调时间)。
DDDD.DDDD 罗马儒略历日期编号是一个浮点数

这些格式中的字符 T 是分隔日期和时间的文本字符“T”。仅包括时间的格式假定日期是 2001-01-01。

修饰符

时间字符串可后跟用于更改日期或更改日期解释的零个或更多个修饰符。可用的修饰符如下:

NNN 天 要添加到时间的天数。
NNN 小时 要添加到时间的小时数。
NNN 分钟 要添加到时间的分钟数。
NNN.NNNN 秒 要添加到时间的秒数和毫秒数。
NNN 月 要添加到时间的月数。
NNN 年 要添加到时间的年数。
一月的开始 将时间后移到一月的开始。
一年的开始 将时间后移到一年的开始。
一天的开始 将时间后移到一天的开始。
工作日 N 将时间前移到指定的工作日。(0 = 星期日,1 = 星期一,依此类推)
本地时间 将日期转换为本地时间
utc 将日期转换为通用协调时间

运算符

SQL 支持大量的运算符(其中包括大多数编程语言中存在的常见运算符)以及 SQL 独有的几个运算符。

常见运算符

在 SQL 块中允许以下二元运算符,它们按从最高到最低的优先顺序列出:

|| * / % + - << >> & | < <= > >= = == != <> IN AND OR

支持的一元前缀运算符是:

- ! ~ NOT

可以认为 COLLATE 运算符是一元后缀运算符。COLLATE 运算符具有最高的优先顺序。它始终比任何一元前缀运算符或任何二元运算符绑定得更紧密。

请注意,等号和不等号运算符各有两个变体。等号可以是 ===。不等号运算符可以是 !=<>

|| 运算符是字符串串联运算符 — 它将其操作数的两个字符串联接在一起。

运算符 % 输出其左操作数以其右操作数为模的余数。

任何二元运算符的结果都是一个数字值,但给出字符串结果的 || 串联运算符除外。

SQL 运算符

LIKE

LIKE 运算符进行模式匹配比较。

expr ::= (column-name | expr) LIKE pattern pattern ::= '[ string | % | _ ]'

LIKE 运算符右侧的操作数包含模式,而左侧的操作数包含对模式进行匹配的字符串。模式中的百分比符号 (%) 是一个通配符 — 它与字符串中零个或更多个字符的任何序列匹配。模式中的下划线 (_) 与字符串中的任何单个字符匹配。任何其他字符与自身匹配,或与其小写/大写形式匹配(即匹配是以不区分大小写的方式执行的)。(注意:数据库引擎仅识别 7 位拉丁字符的大写/小写形式。因此,对于 8 位 iso8859 字符或 UTF-8 字符,LIKE 运算符区分大小写。例如,表达式 'a' LIKE 'A'TRUE,但是 'æ' LIKE 'Æ'FALSE)。可使用 SQLConnection.caseSensitiveLike 属性更改拉丁字符的区分大小写。

如果存在可选的 ESCAPE 子句,则 ESCAPE 关键字后面的表达式的计算结果必须是一个包含单个字符的字符串。可在 LIKE 模式中使用此字符,与文本百分比或下划线字符进行匹配。转义符后跟百分比符号、下划线或转义符本身分别与字符串中的文本百分比符号、下划线或转义符匹配。

GLOB

GLOB 运算符与 LIKE 类似,但是对其通配符使用 Unix 文件名替换语法。与 LIKE 不同,GLOB 区分大小写。

IN

IN 运算符计算其左操作数是否等于其右操作数(括号中的一组值)中的值之一。

in-expr ::= expr [NOT] IN ( value-list ) | expr [NOT] IN ( select-statement ) | expr [NOT] IN [database-name.] table-name value-list ::= literal-value [, literal-value]*

右操作数可以是一组逗号分隔的字面值,或者它可以是 SELECT 语句的结果。有关将 SELECT 语句用作 IN 操作符的右侧操作数的说明和限制,请参阅表达式中的 SELECT 语句。

BETWEEN...AND

BETWEEN...AND 运算符等效于使用两个包含 >=<= 运算符的表达式。例如,表达式 x BETWEEN y AND z 等效于 x >= y AND x <= z

NOT

NOT 运算符是一个求反运算符。可在 GLOBLIKEIN 运算符前面加上 NOT 关键字来反转测试的意义(换句话说,检查一个值是否与指示的模式匹配)。

参数

参数在表达式中指定占位符,用于在运行时通过将值分配给 SQLStatement.parameters 关联数组来填充的字面值。参数可采用以下三种形式:

? 问号指示一个索引参数。根据参数在语句中的顺序,为其分配数字(从零开始的)索引值。
:AAAA 冒号后跟标识符名称保存名为 AAAA 的命名参数的位置。命名参数也是根据它们在 SQL 语句中的顺序编号的。若要避免混淆,最好避免混合使用命名参数和编号参数。
@AAAA “at 符号”等效于冒号。

不支持的 SQL 功能

以下是在 Adobe AIR 中不支持的标准 SQL 元素的列表:

在一些 SQLite 实现中支持以下 SQL 元素和 SQLite 功能,但是在 Adobe AIR 中不支持它们。此功能的大部分可通过 SQLConnection 类的方法获取:

以下功能在许多 SQLite 实现和 Adobe AIR 之间是不同的:

其他 SQL 功能

在 SQLite 中默认情况下不支持以下列关联类型,但是在 Adobe AIR 中支持它们:

在 SQLite 中默认情况下不支持以下字面值,但是在 Adobe AIR 中支持它们:

数据类型支持

与大多数 SQL 数据库不同,Adobe AIR SQL 数据库引擎不要求或强制表列包含某种类型的值。相反,运行时使用两个概念(存储类和列关联)来控制数据类型。本部分介绍存储类和列关联,以及如何在各种情况下解决数据类型差异:

存储类

存储类表示用于在数据库中存储值的实际数据类型。以下存储类是可用的:

对于作为嵌入在 SQL 语句中的文本或使用参数绑定到准备的 SQL 语句的值提供给数据库的所有值,都在执行 SQL 语句之前为其分配存储类。

如果属于 SQL 语句的文本括在单引号或双引号中,则为其分配存储类 TEXT;如果文本被指定为没有小数点或指数的不带引号数字,则分配 INTEGER;如果文本是带有小数点或指数的不带引号数字,则分配 REAL;如果值为 NULL,则分配 NULL。具有存储类 BLOB 的文本是使用 X'ABCD' 表示法指定的。有关详细信息,请参阅表达式中的字面值

对于作为使用 SQLStatement.parameters 关联数组的参数提供的值,为其分配与绑定的本机数据类型最紧密匹配的存储类。例如,int 值作为 INTEGER 存储类绑定,为 Number 值分配 REAL 存储类,为 String 值分配 TEXT 存储类,为 ByteArray 对象分配 BLOB 存储类。

列关联

列的关联是存储在该列中的数据的建议类型。一个值存储在列中(通过 INSERTUPDATE 语句)时,运行时尝试将该值从其数据类型转换为指定的关联。例如,如果将 Date 值(ActionScript 或 JavaScript Date 实例)插入到一个其关联为 TEXT 的列中,则 Date 值在存储于数据库中之前将转换为 String 表示形式(等效于调用对象的 toString() 方法)。如果该值无法转换为指定的关联,则出现错误,且不执行操作。使用 SELECT 语句从数据库中检索值时,它作为对应于关联的类的实例返回,而不管它在被存储时是否已从不同数据类型转换。

如果一个列接受 NULL 值,则 ActionScript 或 JavaScript 值 null 可用作参数值在该列中存储 NULL。当 NULL 存储类值在 SELECT 语句中检索时,它始终作为 ActionScript 或 JavaScript 值 null 返回,而不管列的关联如何。如果一个列接受 NULL 值,则在尝试将值转换成不可为 Null 的类型(如 Number 或 Boolean)之前,始终检查从该列检索的值以确定它们是否为 null

为数据库中的每个列分配以下类型关联之一:

TEXT(或 STRING)

具有 TEXT 或 STRING 关联的列使用存储类 NULL、TEXT 或 BLOB 存储所有数据。如果将数字值插入到具有 TEXT 关联的列中,则在存储它之前将它转换为文本形式。

NUMERIC

具有 NUMERIC 关联的列包含使用存储类 NULL、REAL 或 INTEGER 的值。将文本数据插入到 NUMERIC 列中时,在存储它之前,会尝试将它转换为整数或实数。如果转换成功,则使用 INTEGER 或 REAL 存储类存储值(例如,值 '10.05' 在被存储之前转换为 REAL 存储类)。如果无法执行转换,则出现错误。不会尝试转换 NULL 值。从 NUMERIC 列检索的值作为该值适合的最具体数字类型的实例返回。换句话说,如果该值是一个正整数或 0,则它作为 uint 实例返回。如果它是一个负整数,则它作为 int 实例返回。最后,如果它具有浮点部分(它不是一个整数),则它作为 Number 实例返回。

INTEGER

使用 INTEGER 关联的列的行为方式与具有 NUMERIC 关联的列相同,但有一处不同。如果要存储的值是一个没有浮点部分的实数值(如 Number 实例),或者如果该值是可转换为没有浮点部分的实数值的文本值,则将它转换为整数并使用 INTEGER 存储类存储它。如果尝试存储具有浮点部分的实数值,则出现错误。

REAL(或 NUMBER)

具有 REAL 或 NUMBER 关联的列的行为与具有 NUMERIC 关联的列类似,但是它将整数值强制为浮点表示形式。REAL 列中的值始终作为 Number 实例从数据库返回。

BOOLEAN

具有 BOOLEAN 关联的列存储 true 或 false 值。BOOLEAN 列接受作为 ActionScript 或 JavaScript Boolean 实例的值。如果代码尝试存储字符串值,则将长度大于零的字符串视为 true,并将空字符串视为 false。如果代码尝试存储数字数据,则任何非零值作为 true 存储,而 0 作为 false 存储。使用 SELECT 语句检索 Boolean 值时,它作为 Boolean 实例返回。非 NULL 值是使用 INTEGER 存储类存储的(0 表示 false,1 表示 true),并在检索数据时转换为 Boolean 对象。

DATE

具有 DATE 关联的列存储日期和时间值。DATE 列设计用于接受作为 ActionScript 或 JavaScript Date 实例的值。如果尝试在 DATE 列中存储 String 值,则运行时会尝试将它转换为罗马儒略历日期。如果转换失败,则出现错误。如果代码尝试存储 Number、int 或 uint 值,则不会尝试验证数据,而假定它是有效的罗马儒略历日期值。将使用 SELECT 语句检索的 DATE 值自动转换为 Date 实例。使用 REAL 存储类将 DATE 值存储为罗马儒略历日期值,因此排序和比较操作可以如预期的那样进行。

XML 或 XMLLIST

使用 XML 或 XMLLIST 关联的列存储 XML 结构。当代码尝试使用 SQLStatement 参数在 XML 列中存储数据时,运行时会尝试使用 ActionScript XML()XMLList() 函数转换和验证值。如果该值无法转换为有效的 XML,则出现错误。如果存储数据的尝试使用 SQL 文本字面值(例如 INSERT INTO (col1) VALUES ('Invalid XML (no closing tag)')),则不分析或验证该值 — 而是假定它的格式正确。如果存储了无效值,则在检索它时,它作为空的 XML 对象返回。XML 和 XMLLIST 数据是使用 TEXT 存储类或 NULL 存储类存储的。

OBJECT

具有 OBJECT 关联的列存储 ActionScript 或 JavaScript 复杂对象,其中包括 Object 类实例以及 Object 子类的实例(如 Array 实例,甚至是自定义类实例)。OBJECT 列数据以 AMF3 格式进行序列化,并使用 BLOB 存储类进行存储。在检索一个值时,它从 AMF3 进行反序列化,并在被存储时作为类的实例返回。请注意,某些 ActionScript 类(尤其是显示对象)无法反序列化为其原始数据类型的实例。在存储自定义类实例之前,必须使用 flash.net.registerClassAlias() 方法(或者在 Flex 中,通过向类声明添加 [RemoteObject] 元数据)为该类注册一个别名。此外,在检索该数据之前,必须为类注册相同的别名。无法正确进行反序列化的任何数据(因为类本身无法进行反序列化,或者因为缺少类别名或类别名不匹配),在被存储时作为具有对应于原始实例的属性和值的匿名对象(Object 类实例)返回。

NONE

对于具有关联 NONE 的列,使用任何存储类都是等效的。它不尝试在插入数据之前将其转换。

确定关联

列的类型关联由在 CREATE TABLE 语句中声明的列类型确定。在确定类型时,可应用以下规则:

数据类型与比较运算符

支持以下二元比较运算符 =<<=>=!=,以及测试集合成员身份的运算符 IN 和三元比较运算符 BETWEEN。有关这些运算符的详细信息,请参阅运算符

比较的结果取决于所比较的两个值的存储类。在比较两个值时,可应用以下规则:

在数字存储类和文本存储类之间进行二元比较时,在执行比较之前,数据库会根据需要尝试对值进行转换。在比较数字存储类和文本存储类时,可应用以下规则(注意:在以下规则中使用的术语表达式包括除列值外的任何 SQL 标量表达式或文本。例如,如果 XY.Z 是列名,则认为 +X+Y.Z 是表达式):

始终将三元运算符 BETWEEN 重新转换为等效的二元表达式。例如,a BETWEEN b AND c 将重新转换为 a >= b AND a <= c,即使这意味着在计算表达式所需的每个比较中将不同的关联应用于 a

a IN (SELECT b ....) 类型的表达式由先前为二元比较列举的三个规则处理,即以与 a = b 类似的方式。例如,如果 b 是一个列值,a 是一个表达式,则在进行任何比较之前,将 b 的关联应用于 a。将表达式 a IN (x, y, z) 重新转换为 a = +x OR a = +y OR a = +zIN 运算符右侧的值(此示例中为 xyz 值)被视为表达式,即使它们碰巧是列值。如果 IN 左侧的值是一个列,则使用该列的关联。如果该值是一个表达式,则不发生转换。

执行比较的方式也会受到使用 COLLATE 子句的影响。有关详细信息,请参阅 COLLATE

数据类型与数学运算符

对于每个支持的数学运算符(*/%+-),在计算表达式之前,会将数字关联应用于每个操作数。如果任一操作数无法成功转换为 NUMERIC 存储类,则表达式的计算结果将为 NULL

如果使用了串联运算符 ||,则在计算表达式之前将每个操作数转换为 TEXT 存储类。如果任一操作数无法转换为 TEXT 存储类,则表达式的结果为 NULL。在两种情况下可能发生无法转换值的此问题:操作数的值为 NULL,或者它是包含非 TEXT 存储类的 BLOB。

数据类型与排序

通过 ORDER BY 子句对值排序时,具有存储类 NULL 的值排在最前面。它们后跟按数字顺序散布的 INTEGER 和 REAL 值,再后跟按二进制顺序或基于指定排序规则(BINARYNOCASE)的 TEXT 值。最后是按二进制顺序的 BLOB 值。在排序之前,不发生存储类转换。

数据类型与分组

使用 GROUP BY 子句对值分组时,将具有不同存储类的值视为非重复。例外是 INTEGER 和 REAL 值,如果它们在数值上相等,则认为它们相等。GROUP BY 子句不会导致将关联应用于任何值。

数据类型与复合 SELECT 语句

复合 SELECT 运算符 UNIONINTERSECTEXCEPT 执行值之间的隐式比较。在执行这些比较之前,可能会将关联应用于每个值。相同的关联(如果有)将应用于在复合 SELECT 结果集的单个列中可能返回的所有值。所应用的关联是在该位置中具有列值(而不是其他某种表达式)的第一个构成性 SELECT 语句所返回的列的关联。如果对于给定的复合 SELECT 列,构成性 SELECT 语句都不返回列值,则在对该列中的值进行比较之前,不将关联应用于这些值。

本文档中使用的约定

在本文档的语句定义中,使用了以下约定: