数据定义语句用于创建、修改和删除数据库对象,如表、视图、索引和触发器。支持以下数据定义语句:
-
表:
-
CREATE TABLE
-
ALTER TABLE
-
DROP TABLE
-
-
-
触发器:
-
CREATE TRIGGERS
-
DROP TRIGGERS
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_TIME、CURRENT_DATE 或 CURRENT_TIMESTAMP 之一。如果该值是 NULL、字符串常量或数字,则只要 INSERT 语句不指定列的值,则按字面将它插入到列中。如果该值是 CURRENT_TIME、CURRENT_DATE 或 CURRENT_TIMESTAMP,则将当前的 UTC 日期和/或时间插入到列中。对于 CURRENT_TIME,格式为 HH:MM:SS。对于 CURRENT_DATE,格式为 YYYY-MM-DD。CURRENT_TIMESTAMP 的格式为 YYYY-MM-DD HH:MM:SS。
指定 PRIMARY KEY 通常仅在对应的一个或多个列上创建 UNIQUE 索引。但是,如果 PRIMARY KEY 约束在具有数据类型 INTEGER(或它的一个同义词,如 int)的单个列上,则数据库会将该列用作表的实际主键。这意味着该列只能保存唯一整数值。(注意:在许多 SQLite 实现中,只有列类型 INTEGER 会导致列用作内部主键,但在 Adobe AIR 中,INTEGER 的同义词,如 int,也会指定该行为。)
如果表没有 INTEGER PRIMARY KEY 列,则在插入行时将自动生成整数键。使用特殊名称 ROWID、OID 或 _ROWID_ 之一,始终可以访问行的主键。可使用这些名称,而不管它是明确声明的 INTEGER PRIMARY KEY 还是内部生成的值。但是,如果表具有显式 INTEGER PRIMARY KEY,则结果数据中的列名称是实际列名称,而不是特殊名称。
INTEGER PRIMARY KEY 列还可包括关键字 AUTOINCREMENT。如果使用 AUTOINCREMENT 关键字,则在执行未指定列的显式值的 INSERT 语句时,数据库会在 INTEGER PRIMARY KEY 列中自动生成并插入按顺序递增的整数键。
CREATE TABLE 语句中只能有一个 PRIMARY KEY 约束。它可以是一个列的定义的一部分或一个单表级 PRIMARY KEY 约束。主键列隐式为 NOT NULL。
许多约束后面的可选 conflict-clause 允许为该约束指定替代的默认约束冲突解决算法。默认值为 ABORT。同一表中的不同约束可能具有不同的默认冲突解决算法。如果 INSERT 或 UPDATE 语句指定不同的冲突解决算法,则使用该算法,替代在 CREATE TABLE 语句中指定的算法。请参阅
特殊的语句和子句
的 ON CONFLICT 部分,了解更多信息。
其他约束(如 FOREIGN KEY 约束)不会导致错误,但运行时会忽略它们。
如果在 CREATE 和 TABLE 之间出现 TEMP 或 TEMPORARY 关键字,则创建的表仅在同一数据库连接(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 语句中允许的任何形式,但有以下限制:
-
列不能具有 PRIMARY KEY 或 UNIQUE 约束。
-
列不能具有默认值 CURRENT_TIME、CURRENT_DATE 或 CURRENT_TIMESTAMP。
-
如果指定了 NOT NULL 约束,则列必须具有除 NULL 之外的默认值。
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]
每个列名都可后跟 ASC 或 DESC 关键字以指示排序顺序,但运行时会忽略指定的排序顺序。排序始终按升序执行。
每个列名后面的 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
如果在 CREATE 和 VIEW 之间出现 TEMP 或 TEMPORARY 关键字,则创建的视图仅对已打开数据库的 SQLConnection 实例是可见的,并且在关闭数据库时会自动删除该视图。
如果指定了 [database-name],则使用指定的 name 参数在指定的数据库(使用 attach() 方法连接到 SQLConnection 实例的数据库)中创建视图。除非 [database-name] 是 temp,否则同时指定 [database-name] 和 TEMP 关键字是错误的。如果未指定数据库名称,而且不存在 TEMP 关键字,则在主数据库(使用 open() 或 openAsync() 方法连接到 SQLConnection 实例的数据库)中创建视图。
视图是只读的。除非至少定义一个关联类型(INSTEAD OF DELETE、INSTEAD OF INSERT、INSTEAD OF UPDATE)的触发器,否则不能对视图使用 DELETE、INSERT 或 UPDATE 语句。有关为视图创建触发器的信息,请参阅 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]*
触发器被指定为只要出现以下条件就会激发:发生特定数据库表的 DELETE、INSERT 或 UPDATE,或者更新了表的一个或多个指定列的 UPDATE。除非使用了 TEMP 或 TEMPORARY 关键字,否则触发器是永久性的。在这种情况下,当关闭 SQLConnection 实例的主数据库连接时,将删除触发器。如果未指定时间(BEFORE 或 AFTER),则触发器默认为 BEFORE。
仅支持 FOR EACH ROW 触发器,因此 FOR EACH ROW 文本是可选的。对于 FOR EACH ROW 触发器,如果 WHEN 子句表达式的计算结果为 true,则对导致触发器激发的语句所插入、更新或删除的每个数据库行执行 trigger-step 语句。
如果提供了 WHEN 子句,则仅对 WHEN 子句为 true 的行执行指定为触发器步骤的 SQL 语句。如果未提供 WHEN 子句,则对所有行执行 SQL 语句。
在触发器体(trigger-action 子句)中,受影响表的更改之前值和更改之后值使用特殊的表名 OLD 和 NEW 提供。OLD 和 NEW 表的结构与创建触发器的表的结构匹配。OLD 表包含由触发语句修改或删除的任何行,处于其在触发语句操作之前的状态。NEW 表包含由触发语句修改或创建的任何行,处于其在触发语句操作之后的状态。WHEN 子句和 trigger-step 语句都可访问使用 NEW.column-name 和 OLD.column-name 形式的引用插入、删除或更新的行的值,其中 column-name 是与触发器关联的表中的列的名称。OLD 和 NEW 表引用的可用性取决于触发器所处理的 database-event 类型:
-
INSERT – NEW 引用有效
-
UPDATE – NEW 和 OLD 引用有效
-
DELETE – OLD 引用有效
指定的时间(BEFORE、AFTER 或 INSTEAD OF)确定何时执行与插入、修改或删除关联行有关的 trigger-step 语句。可将 ON CONFLICT 子句指定为 trigger-step 中 UPDATE 或 INSERT 语句的一部分。但是,如果将 ON CONFLICT 子句指定为导致触发器激发的语句的一部分,则改用该冲突处理策略。
除了表触发器外,还可在视图上创建 INSTEAD OF 触发器。如果在某个视图上定义了一个或多个 INSTEAD OF INSERT、INSTEAD OF DELETE 或 INSTEAD OF UPDATE 触发器,则在该视图上执行关联类型的语句(INSERT、DELETE 或 UPDATE)不会被视为错误。在这种情况下,在视图上执行 INSERT、DELETE 或 UPDATE 会导致关联触发器激发。由于触发器是 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 处理操作(ABORT、FAIL 或 ROLLBACK),而且当前语句的执行结束。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
将从数据库中删除触发器。请注意,在删除其关联表时,会自动删除触发器。