1. 语法
创建表stmt:
隐藏
CREATE
TEMP
TEMPORARY
TABLE
IF
NOT
EXISTS
schema-name
.
table-name
(
column-def
table-constraint
,
)
WITHOUT
ROWID
,
AS
select-stmt
列定义:
表演
column-name
type-name
column-constraint
列约束:
表演
CONSTRAINT
name
PRIMARY
KEY
DESC
conflict-clause
AUTOINCREMENT
ASC
NOT
NULL
conflict-clause
UNIQUE
conflict-clause
CHECK
(
expr
)
DEFAULT
(
expr
)
literal-value
signed-number
COLLATE
collation-name
foreign-key-clause
GENERATED
ALWAYS
AS
(
expr
)
VIRTUAL
STORED
冲突条款:
表演
ON
CONFLICT
ROLLBACK
ABORT
FAIL
IGNORE
REPLACE
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
过滤器子句:
表演
子句:
表演
OVER
window-name
(
base-window-name
PARTITION
BY
expr
,
ORDER
BY
ordering-term
,
frame-spec
)
框架规格:
表演
GROUPS
BETWEEN
UNBOUNDED
PRECEDING
AND
UNBOUNDED
FOLLOWING
RANGE
ROWS
UNBOUNDED
PRECEDING
expr
PRECEDING
CURRENT
ROW
expr
PRECEDING
CURRENT
ROW
expr
FOLLOWING
expr
PRECEDING
CURRENT
ROW
expr
FOLLOWING
EXCLUDE
CURRENT
ROW
EXCLUDE
GROUP
EXCLUDE
TIES
EXCLUDE
NO
OTHERS
订购期限:
表演
expr
COLLATE
collation-name
DESC
ASC
NULLS
FIRST
NULLS
LAST
提升功能:
表演
RAISE
(
ROLLBACK
,
error-message
)
IGNORE
ABORT
FAIL
外键子句:
表演
REFERENCES
foreign-table
(
column-name
)
,
ON
DELETE
SET
NULL
UPDATE
SET
DEFAULT
CASCADE
RESTRICT
NO
ACTION
MATCH
name
NOT
DEFERRABLE
INITIALLY
DEFERRED
INITIALLY
IMMEDIATE
文字值:
表演
CURRENT_TIMESTAMP
numeric-literal
string-literal
blob-literal
NULL
TRUE
FALSE
CURRENT_TIME
CURRENT_DATE
签名编号:
表演
类型名称:
表演
name
(
signed-number
,
signed-number
)
(
signed-number
)
签名编号:
表演
select-stmt:
表演
WITH
RECURSIVE
common-table-expression
,
SELECT
DISTINCT
result-column
,
ALL
FROM
table-or-subquery
join-clause
,
WHERE
expr
GROUP
BY
expr
HAVING
expr
,
WINDOW
window-name
AS
window-defn
,
VALUES
(
expr
)
,
,
compound-operator
select-core
ORDER
BY
LIMIT
expr
ordering-term
,
OFFSET
expr
,
expr
common-table-expression:
表演
table-name
(
column-name
)
AS
NOT
MATERIALIZED
(
select-stmt
)
,
复合运算符:
表演
UNION
UNION
INTERSECT
EXCEPT
ALL
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
过滤器子句:
表演
文字值:
表演
CURRENT_TIMESTAMP
numeric-literal
string-literal
blob-literal
NULL
TRUE
FALSE
CURRENT_TIME
CURRENT_DATE
子句:
表演
OVER
window-name
(
base-window-name
PARTITION
BY
expr
,
ORDER
BY
ordering-term
,
frame-spec
)
框架规格:
表演
GROUPS
BETWEEN
UNBOUNDED
PRECEDING
AND
UNBOUNDED
FOLLOWING
RANGE
ROWS
UNBOUNDED
PRECEDING
expr
PRECEDING
CURRENT
ROW
expr
PRECEDING
CURRENT
ROW
expr
FOLLOWING
expr
PRECEDING
CURRENT
ROW
expr
FOLLOWING
EXCLUDE
CURRENT
ROW
EXCLUDE
GROUP
EXCLUDE
TIES
EXCLUDE
NO
OTHERS
提升功能:
表演
RAISE
(
ROLLBACK
,
error-message
)
IGNORE
ABORT
FAIL
类型名称:
表演
name
(
signed-number
,
signed-number
)
(
signed-number
)
签名编号:
表演
加盟条款:
表演
table-or-subquery
join-operator
table-or-subquery
join-constraint
连接约束:
表演
USING
(
column-name
)
,
ON
expr
加入运营商:
表演
NATURAL
LEFT
OUTER
JOIN
,
INNER
CROSS
订购期限:
表演
expr
COLLATE
collation-name
DESC
ASC
NULLS
FIRST
NULLS
LAST
结果栏:
表演
expr
AS
column-alias
*
table-name
.
*
表或子查询:
表演
schema-name
.
table-name
AS
table-alias
INDEXED
BY
index-name
NOT
INDEXED
table-function-name
(
expr
)
,
AS
table-alias
(
select-stmt
)
(
table-or-subquery
)
,
join-clause
表约束:
表演
CONSTRAINT
name
PRIMARY
KEY
(
indexed-column
)
conflict-clause
,
UNIQUE
CHECK
(
expr
)
FOREIGN
KEY
(
column-name
)
foreign-key-clause
,
冲突条款:
表演
ON
CONFLICT
ROLLBACK
ABORT
FAIL
IGNORE
REPLACE
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
过滤器子句:
表演
文字值:
表演
CURRENT_TIMESTAMP
numeric-literal
string-literal
blob-literal
NULL
TRUE
FALSE
CURRENT_TIME
CURRENT_DATE
子句:
表演
OVER
window-name
(
base-window-name
PARTITION
BY
expr
,
ORDER
BY
ordering-term
,
frame-spec
)
框架规格:
表演
GROUPS
BETWEEN
UNBOUNDED
PRECEDING
AND
UNBOUNDED
FOLLOWING
RANGE
ROWS
UNBOUNDED
PRECEDING
expr
PRECEDING
CURRENT
ROW
expr
PRECEDING
CURRENT
ROW
expr
FOLLOWING
expr
PRECEDING
CURRENT
ROW
expr
FOLLOWING
EXCLUDE
CURRENT
ROW
EXCLUDE
GROUP
EXCLUDE
TIES
EXCLUDE
NO
OTHERS
订购期限:
表演
expr
COLLATE
collation-name
DESC
ASC
NULLS
FIRST
NULLS
LAST
提升功能:
表演
RAISE
(
ROLLBACK
,
error-message
)
IGNORE
ABORT
FAIL
类型名称:
表演
name
(
signed-number
,
signed-number
)
(
signed-number
)
签名编号:
表演
外键子句:
表演
REFERENCES
foreign-table
(
column-name
)
,
ON
DELETE
SET
NULL
UPDATE
SET
DEFAULT
CASCADE
RESTRICT
NO
ACTION
MATCH
name
NOT
DEFERRABLE
INITIALLY
DEFERRED
INITIALLY
IMMEDIATE
索引栏:
表演
column-name
COLLATE
collation-name
DESC
expr
ASC
2. CREATE TABLE命令
“创建表”命令用于在SQLite数据库中创建新表。CREATE TABLE命令指定新表的以下属性:
新表的名称。
在其中创建新表的数据库。可以在主数据库,临时数据库或任何附加数据库中创建表。
表中每列的名称。
表中每列的声明类型。
表中每列的默认值或表达式。
每列使用的默认排序规则序列。
(可选)表的主键。单列和复合(多列)主键均受支持。
每个表的一组SQL约束。SQLite支持UNIQUE,NOT NULL,CHECK和FOREIGN KEY约束。
(可选)生成的列 约束。
该表是否为WITHOUT ROWID 表。
每个CREATE TABLE语句必须为新表指定一个名称。以“ sqlite_”开头的表名保留供内部使用。尝试创建名称以“ sqlite_”开头的表是错误的。
如果指定了架构名称 ,则它必须是“ main”,“ temp”或附加数据库 的名称。在这种情况下,新表将在命名数据库中创建。如果在“创建”和“表”之间出现“ TEMP”或“ TEMPORARY”关键字,则将在temp数据库中创建新表。同时指定架构名称 和TEMP或TEMPORARY关键字是错误的
,除非
架构名称 为“ temp”。如果未指定架构名称且不存在TEMP关键字,则在主数据库中创建表。
试图在已经包含相同名称的表,索引或视图的数据库中创建新表通常是错误的。但是,如果将“ IF NOT EXISTS”子句指定为CREATE TABLE语句的一部分,并且已经存在相同名称的表或视图,则CREATE TABLE命令将完全无效(并且不会返回错误消息)。如果由于存在索引而无法创建表,即使指定了“ IF NOT EXISTS”子句,仍然会返回错误。
创建与现有触发器 同名的表不是错误。
使用DROP TABLE 语句删除表 。
2.1。 CREATE TABLE ... AS SELECT语句
“ CREATE TABLE ... AS SELECT”语句根据SELECT语句的结果创建并填充数据库表。该表的列数与SELECT语句返回的行数相同。每列的名称与SELECT语句的结果集中相应列的名称相同。每列的声明类型由SELECT语句的结果集中相应表达式的表达式亲和力 确定,如下所示:
表达亲和力 列声明类型
文本 “文本”
数字 “ NUM”
整数 “ INT”
真实的 “真实的”
BLOB(又名“ NONE”) “”(空字符串)
使用CREATE TABLE AS创建的表没有PRIMARY KEY,也没有任何类型的约束。每列的默认值为NULL。新表的每一列的默认排序规则序列为BINARY。
使用CREATE TABLE AS创建的表最初会填充SELECT语句返回的数据行。按SELECT语句返回的顺序 ,行从1开始连续分配给rowid 值。
3. 列定义
除非它是CREATE TABLE ... AS SELECT语句,否则CREATE TABLE包含一个或多个列定义 ,还可以选择包含表约束 列表
。每个列定义都由列名组成,可选地后跟列的声明类型,然后是一个或多个可选列约束 。就上一条语句而言,“列约束”的定义中包括COLLATE和DEFAULT子句,即使这些并不是真正的约束,因为它们并不限制表可能包含的数据。其他约束-NOT NULL,CHECK,UNIQUE,PRIMARY KEY和FOREIGN KEY约束-对表数据施加约束。
表中的列数受SQLITE_MAX_COLUMN
编译时参数的限制。表的一行不能存储超过
SQLITE_MAX_LENGTH 个字节的数据。使用sqlite3_limit() C / C ++接口可以在运行时降低这两个限制。
3.1。 列数据类型
与大多数SQL数据库不同,SQLite不会根据声明的列类型限制可插入到列中的数据类型。相反,SQLite使用动态类型 。列的声明类型仅用于确定列的亲和力 。
3.2。 DEFAULT子句
如果用户在执行INSERT 时未明确提供任何值,则DEFAULT子句指定用于该列的默认值。如果没有显式的DEFAULT子句附加到列定义,则该列的默认值为NULL。显式的DEFAULT子句可以指定默认值为NULL,字符串常量,blob常量,带符号的数字或括号中包含的任何常量表达式。默认值也可以是与大小写无关的特殊关键字之一CURRENT_TIME,CURRENT_DATE或CURRENT_TIMESTAMP。就DEFAULT子句而言,如果表达式不包含用双引号而不是单引号引起来的子查询,列或表引用,绑定参数 或字符串文字,则该表达式被视为常量。
每次通过不为所有表列提供显式值的INSERT语句将表插入表中时,存储在新行中的值均由其默认值确定,如下所示:
如果该列的默认值是常量NULL,文本,blob或带符号的值,则该值将直接在新行中使用。
如果列的默认值是用括号括起来的表达式,则对插入的每一行对该表达式进行一次评估,并将结果用于新行。
如果列的默认值为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”。
3.3。 COLLATE子句
COLLATE子句指定排序规则序列 的名称,用作该列的默认排序规则序列。如果未指定COLLATE子句,则默认排序规则序列为BINARY 。
3.4。 GENERATED ALWAYS AS子句
包含GENERATED ALWAY AS子句的列 是生成的列 。从SQLite版本3.31.0(2020-01-22)开始支持生成的列。有关生成列的功能和限制的详细信息,请参见单独的文档 。
3.5。 主键
SQLite中的每个表最多可以具有一个PRIMARY KEY。如果将关键字PRIMARY KEY添加到列定义,则表的主键由该单个列组成。或者,如果将PRIMARY KEY子句指定为table-constraint ,则表 的主键由指定为PRIMARY KEY子句的一部分的列列表组成。PRIMARY KEY子句必须仅包含列名-不支持在PRIMARY KEY的索引列 中使用表达式。如果CREATE TABLE语句中出现多个PRIMARY KEY子句,则会引发错误。PRIMARY KEY对于普通表是可选的,但对于WITHOUT ROWID 表则是必需的。
如果表具有单个列主键,并且该列的声明类型为“ INTEGER”,并且该表不是WITHOUT ROWID 表,则该列称为INTEGER PRIMARY KEY 。有关与INTEGER PRIMARY KEY 关联的特殊属性和行为的说明,请参见下文 。
具有主键的表中的每一行在其主键列中必须具有唯一的值组合。为了确定主键值的唯一性,将NULL值视为与所有其他值(包括其他NULL)不同。如果INSERT 或UPDATE
语句尝试修改表内容,以使两行或更多行具有相同的主键值,则违反约束。
根据SQL标准,PRIMARY KEY应该始终暗示NOT NULL。不幸的是,由于某些早期版本中的错误,在SQLite中不是这种情况。除非该列是INTEGER PRIMARY KEY 或表是WITHOUT ROWID 表或将该列声明为NOT NULL,否则SQLite允许在PRIMARY KEY列中使用NULL值。可以修复SQLite以使其符合标准,但是这样做可能会破坏旧版应用程序。因此,决定仅记录SQLite在大多数PRIMARY KEY列中允许NULL的事实。
3.6。 唯一约束
UNIQUE约束与PRIMARY KEY约束相似,不同之处在于单个表可以具有任意数量的UNIQUE约束。对于表上的每个UNIQUE约束,每一行都必须在由UNIQUE约束标识的列中包含值的唯一组合。出于UNIQUE约束的目的,NULL值被认为与所有其他值(包括其他NULL)不同。与PRIMARY KEYs一样,UNIQUE table-constraint 子句必须仅包含列名-
不支持在UNIQUE table-constraint 的索引列 中使用表达式。
在大多数情况下,通过在数据库中创建唯一索引来实现UNIQUE和PRIMARY KEY约束。(例外是WITHOUT ROWID 表上的INTEGER PRIMARY KEY 和PRIMARY KEY
。)因此,以下模式在逻辑上是等效的:
创建表t1(a,b UNIQUE);
创建表t1(a,b主键);
创建表t1(a,b);
在t1(b)上创建唯一索引t1b;
3.7。 检查约束
CHECK约束可以附加到列定义或指定为表约束。实际上,这没有什么区别。每次将新行插入表中或更新现有行时,都会评估与每个CHECK约束关联的表达式,并将其转换为NUMERIC值,方法与CAST表达式 相同。如果结果为零(整数值0或实数值0.0),则发生约束冲突。如果CHECK表达式的计算结果为NULL或任何其他非零值,则不是约束冲突。CHECK约束的表达式可能不包含子查询。
3.8。 非空约束
NOT NULL约束只能附加到列定义,而不能指定为表约束。毫不奇怪,NOT NULL约束指示关联的列可能不包含NULL值。在插入新行或更新现有行时尝试将列值设置为NULL会导致约束冲突。
4. 违反约束
约束冲突解决算法 确定了如何处理
约束冲突 。每个PRIMARY KEY,UNIQUE,NOT NULL和CHECK约束都有一个默认的冲突解决算法。通过在其定义中包含冲突子句 ,可以显式分配PRIMARY KEY,UNIQUE和NOT NULL约束,作为默认的冲突解决算法。或者,如果约束定义不包含冲突子句 或它是CHECK约束,则默认冲突解决算法为ABORT。同一张表中的不同约束可能具有不同的默认冲突解决算法。有关其他信息,请参见标题为“冲突 ”。
5. ROWID和整数主键
除了WITHOUT ROWID 表外,SQLite表中的所有行都有一个64位带符号整数键,该键唯一地标识其表中的行。该整数通常称为“ rowid”。可以使用与大小写无关的特殊名称之一“ rowid”,“ oid”或“ _rowid_”代替列名来访问rowid值。如果表包含用户定义的名为“ rowid”,“ oid”或“ _rowid_”的列,则该名称始终引用显式声明的列,并且不能用于检索整数rowid值。
在WITHOUT ROWID 表中省略了rowid(以及“ oid”和“ _rowid_”)。WITHOUT ROWID表仅在SQLite 3.8.2
(2013-12-06)及更高版本中 可用。缺少WITHOUT ROWID子句的表称为“ rowid表”。
使用rowid值作为键,rowid表的数据存储为B树结构,其中每个表行包含一个条目。这意味着按rowid检索或排序记录很快。搜索具有特定rowid的记录,或搜索具有指定范围内的rowid的所有记录的速度大约是通过指定任何其他PRIMARY KEY或索引值进行的类似搜索的两倍。
除了下面提到的一个例外,如果rowid表的主键由单个列组成,并且该列的声明类型为大写和小写形式的“ INTEGER”,则该列将成为rowid的别名。这样的列通常称为“整数主键”。仅当声明的类型名称恰好是“ INTEGER”时,PRIMARY KEY列才成为整数主键。其他整数类型名称(例如“ INT”或“ BIGINT”或“ SHORT INTEGER”或“ UNSIGNED INTEGER”)会导致主键列的行为与具有整数相似性 和唯一索引的普通表列相同,而不是作为rowid的别名。
上面提到的例外是,如果声明类型为“ INTEGER”的列的声明包含“ PRIMARY KEY DESC”子句,则它不会成为rowid的别名,也不会归类为整数主键。这个怪癖不是故意的。这是由于早期SQLite版本中的错误所致。但是修复该错误可能会导致向后不兼容。因此,原始行为得以保留(并记录在案),因为在极端情况下的奇怪行为远胜于兼容性破坏。这意味着以下三个表声明都使列“ x”成为rowid(整数主键)的别名:
创建表t(x整数主键ASC,y,z);
创建表t(x INTEGER,y,z,主键(x ASC));
创建表t(x INTEGER,y,z,主键(x DESC));
但是以下声明不会导致“ x”成为rowid的别名:
可以使用UPDATE语句以与其他任何列值相同的方式修改Rowid值,可以使用内置别名之一(“ rowid”,“ oid”或“ _rowid_”),也可以使用由整数主键。同样,INSERT语句可以提供一个值,用作插入的每一行的行标识。与普通的SQLite列不同,整数主键或rowid列必须包含整数值。整数主键或rowid列不能保存浮点值,字符串,BLOB或NULL。
如果UPDATE语句尝试将整数主键或rowid列设置为NULL或blob值,或者将其设置为无法无损地转换为整数的字符串或实数值,则会发生“数据类型不匹配”错误,并且该语句将中止。如果INSERT语句尝试将blob值或无法无损地转换为整数的字符串或实值插入整数主键或rowid列,则会发生“数据类型不匹配”错误,并且该语句将中止。
如果INSERT语句尝试将NULL值插入到rowid或整数主键列中,则系统会自动选择一个整数值用作rowid。单独 提供了有关此操作的详细说明
。
该父键 一个的外键约束 ,不允许使用ROWID。父键只能使用命名列。