1. 概述
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
)
,
compound-operator
显示
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
(
function-arguments
)
filter-clause
over-clause
(
expr
)
,
CAST
(
expr
AS
type-name
)
expr
COLLATE
collation-name
expr
NOT
LIKE
GLOB
REGEXP
MATCH
expr
expr
ESCAPE
expr
expr
ISNULL
NOTNULL
NOT
NULL
expr
IS
NOT
DISTINCT
FROM
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
filter-clause
显示
function-arguments
显示
DISTINCT
expr
,
*
ORDER
BY
ordering-term
,
literal-value
显示
CURRENT_TIMESTAMP
numeric-literal
string-literal
blob-literal
NULL
TRUE
FALSE
CURRENT_TIME
CURRENT_DATE
over-clause
显示
OVER
window-name
(
base-window-name
PARTITION
BY
expr
,
ORDER
BY
ordering-term
,
frame-spec
)
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-function
显示
RAISE
(
ROLLBACK
,
error-message
)
IGNORE
ABORT
FAIL
type-name
显示
name
(
signed-number
,
signed-number
)
(
signed-number
)
signed-number
显示
join-clause
显示
table-or-subquery
join-operator
table-or-subquery
join-constraint
join-constraint
显示
USING
(
column-name
)
,
ON
expr
join-operator
显示
NATURAL
LEFT
OUTER
JOIN
,
RIGHT
FULL
INNER
CROSS
ordering-term
显示
expr
COLLATE
collation-name
DESC
ASC
NULLS
FIRST
NULLS
LAST
result-column
显示
expr
AS
column-alias
*
table-name
.
*
table-or-subquery
显示
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
window-defn
显示
(
base-window-name
PARTITION
BY
expr
,
ORDER
BY
ordering-term
,
frame-spec
)
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
SELECT 语句用于查询数据库。SELECT 的结果是零行或多行数据,其中每行具有固定数量的列。SELECT 语句不会对数据库进行任何更改。
上面的“select-stmt ”语法图试图在一个图中显示尽可能多的 SELECT 语句语法,因为一些读者发现这很有帮助。下面的“factored-select-stmt ”是另一种语法图,它表达了相同的语法,但试图将语法分解成更小的块。
factored-select-stmt
显示
WITH
RECURSIVE
common-table-expression
,
select-core
ORDER
BY
LIMIT
expr
compound-operator
ordering-term
,
OFFSET
expr
,
expr
common-table-expression
显示
table-name
(
column-name
)
AS
NOT
MATERIALIZED
(
select-stmt
)
,
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
join-clause
显示
table-or-subquery
join-operator
table-or-subquery
join-constraint
join-constraint
显示
USING
(
column-name
)
,
ON
expr
join-operator
显示
NATURAL
LEFT
OUTER
JOIN
,
RIGHT
FULL
INNER
CROSS
result-column
显示
expr
AS
column-alias
*
table-name
.
*
table-or-subquery
显示
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
window-defn
显示
(
base-window-name
PARTITION
BY
expr
,
ORDER
BY
ordering-term
,
frame-spec
)
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
compound-operator
显示
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
(
function-arguments
)
filter-clause
over-clause
(
expr
)
,
CAST
(
expr
AS
type-name
)
expr
COLLATE
collation-name
expr
NOT
LIKE
GLOB
REGEXP
MATCH
expr
expr
ESCAPE
expr
expr
ISNULL
NOTNULL
NOT
NULL
expr
IS
NOT
DISTINCT
FROM
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
filter-clause
显示
function-arguments
显示
DISTINCT
expr
,
*
ORDER
BY
ordering-term
,
literal-value
显示
CURRENT_TIMESTAMP
numeric-literal
string-literal
blob-literal
NULL
TRUE
FALSE
CURRENT_TIME
CURRENT_DATE
over-clause
显示
OVER
window-name
(
base-window-name
PARTITION
BY
expr
,
ORDER
BY
ordering-term
,
frame-spec
)
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-function
显示
RAISE
(
ROLLBACK
,
error-message
)
IGNORE
ABORT
FAIL
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
join-clause
显示
table-or-subquery
join-operator
table-or-subquery
join-constraint
join-constraint
显示
USING
(
column-name
)
,
ON
expr
join-operator
显示
NATURAL
LEFT
OUTER
JOIN
,
RIGHT
FULL
INNER
CROSS
result-column
显示
expr
AS
column-alias
*
table-name
.
*
table-or-subquery
显示
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
window-defn
显示
(
base-window-name
PARTITION
BY
expr
,
ORDER
BY
ordering-term
,
frame-spec
)
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
type-name
显示
name
(
signed-number
,
signed-number
)
(
signed-number
)
signed-number
显示
ordering-term
显示
expr
COLLATE
collation-name
DESC
ASC
NULLS
FIRST
NULLS
LAST
select-core
显示
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
)
,
,
join-clause
显示
table-or-subquery
join-operator
table-or-subquery
join-constraint
join-constraint
显示
USING
(
column-name
)
,
ON
expr
join-operator
显示
NATURAL
LEFT
OUTER
JOIN
,
RIGHT
FULL
INNER
CROSS
result-column
显示
expr
AS
column-alias
*
table-name
.
*
table-or-subquery
显示
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
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
window-defn
显示
(
base-window-name
PARTITION
BY
expr
,
ORDER
BY
ordering-term
,
frame-spec
)
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
请注意,在语法图中存在一些在实践中不允许的路径。一些例子
这些和其他类似的语法限制在文本中进行了描述。
SELECT 语句是 SQL 语言中最复杂的命令。为了使描述更容易理解,下面的一些段落将返回 SELECT 语句的数据的方式描述为一系列步骤。重要的是要记住,这纯粹是为了说明 - 在实践中,SQLite 或任何其他 SQL 引擎都不需要遵循此过程或任何其他特定过程。
2. 简单 SELECT 处理
SELECT 语句的核心是“简单 SELECT”,由下面的 select-core 和 simple-select-stmt 语法图所示。在实践中,大多数 SELECT 语句都是简单 SELECT 语句。
simple-select-stmt
隐藏
WITH
RECURSIVE
common-table-expression
,
select-core
ORDER
BY
LIMIT
expr
ordering-term
,
OFFSET
expr
,
expr
common-table-expression
显示
table-name
(
column-name
)
AS
NOT
MATERIALIZED
(
select-stmt
)
,
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
compound-operator
显示
UNION
UNION
INTERSECT
EXCEPT
ALL
join-clause
显示
table-or-subquery
join-operator
table-or-subquery
join-constraint
join-constraint
显示
USING
(
column-name
)
,
ON
expr
join-operator
显示
NATURAL
LEFT
OUTER
JOIN
,
RIGHT
FULL
INNER
CROSS
result-column
显示
expr
AS
column-alias
*
table-name
.
*
table-or-subquery
显示
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
window-defn
显示
(
base-window-name
PARTITION
BY
expr
,
ORDER
BY
ordering-term
,
frame-spec
)
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
显示
literal-value
bind-parameter
schema-name
.
table-name
.
column-name
unary-operator
expr
expr
binary-operator
expr
function-name
(
function-arguments
)
filter-clause
over-clause
(
expr
)
,
CAST
(
expr
AS
type-name
)
expr
COLLATE
collation-name
expr
NOT
LIKE
GLOB
REGEXP
MATCH
expr
expr
ESCAPE
expr
expr
ISNULL
NOTNULL
NOT
NULL
expr
IS
NOT
DISTINCT
FROM
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
filter-clause
显示
function-arguments
显示
DISTINCT
expr
,
*
ORDER
BY
ordering-term
,
literal-value
显示
CURRENT_TIMESTAMP
numeric-literal
string-literal
blob-literal
NULL
TRUE
FALSE
CURRENT_TIME
CURRENT_DATE
over-clause
显示
OVER
window-name
(
base-window-name
PARTITION
BY
expr
,
ORDER
BY
ordering-term
,
frame-spec
)
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-function
显示
RAISE
(
ROLLBACK
,
error-message
)
IGNORE
ABORT
FAIL
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
compound-operator
显示
UNION
UNION
INTERSECT
EXCEPT
ALL
join-clause
显示
table-or-subquery
join-operator
table-or-subquery
join-constraint
join-constraint
显示
USING
(
column-name
)
,
ON
expr
join-operator
显示
NATURAL
LEFT
OUTER
JOIN
,
RIGHT
FULL
INNER
CROSS
result-column
显示
expr
AS
column-alias
*
table-name
.
*
table-or-subquery
显示
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
window-defn
显示
(
base-window-name
PARTITION
BY
expr
,
ORDER
BY
ordering-term
,
frame-spec
)
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
type-name
显示
name
(
signed-number
,
signed-number
)
(
signed-number
)
signed-number
显示
ordering-term
显示
expr
COLLATE
collation-name
DESC
ASC
NULLS
FIRST
NULLS
LAST
select-core
隐藏
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
)
,
,
join-clause
显示
table-or-subquery
join-operator
table-or-subquery
join-constraint
join-constraint
显示
USING
(
column-name
)
,
ON
expr
join-operator
显示
NATURAL
LEFT
OUTER
JOIN
,
RIGHT
FULL
INNER
CROSS
result-column
显示
expr
AS
column-alias
*
table-name
.
*
table-or-subquery
显示
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
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
compound-operator
显示
UNION
UNION
INTERSECT
EXCEPT
ALL
window-defn
显示
(
base-window-name
PARTITION
BY
expr
,
ORDER
BY
ordering-term
,
frame-spec
)
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
生成简单 SELECT 语句的结果在下面的描述中表示为一个四步过程
FROM 子句 处理:确定简单 SELECT 的输入数据。输入数据要么隐式地是一行 0 列(如果没有 FROM 子句),要么由 FROM 子句确定。
WHERE 子句 处理:使用 WHERE 子句表达式过滤输入数据。
GROUP BY、HAVING 和结果列表达式 处理:通过根据任何 GROUP BY 子句聚合数据并计算过滤后的输入数据集行的结果集表达式来计算结果行集。
DISTINCT/ALL 关键字 处理:如果查询是“SELECT DISTINCT”查询,则从结果行集中删除重复行。
简单 SELECT 语句有两种类型:聚合查询和非聚合查询。如果简单 SELECT 语句包含 GROUP BY 子句或结果集中一个或多个聚合函数,则它是一个聚合查询。否则,如果简单 SELECT 不包含聚合函数或 GROUP BY 子句,则它是一个非聚合查询。
简单 SELECT 查询使用的输入数据是一组N 行,每行M 列宽。
如果从简单 SELECT 语句中省略 FROM 子句,则输入数据隐式地为一行零列宽(即N =1 且M =0)。
如果指定了 FROM 子句,则简单 SELECT 查询操作的数据来自在 FROM 关键字后指定的表或子查询(括号中的 SELECT 语句)之一或多个。简单 SELECT 语句中 FROM 子句后 table-or-subquery 中指定的子查询的处理方式就像它是一个包含执行子查询语句返回的数据的表一样。子查询的每一列都具有子查询语句中相应表达式的排序规则 和亲和性 。
如果 FROM 子句中只有一个表或子查询,则 SELECT 语句使用的输入数据是命名表的表内容。如果 FROM 子句中有多个表或子查询,则所有表和/或子查询的内容将连接到一个数据集中,供简单 SELECT 语句操作。数据如何组合取决于用于将表或子查询连接在一起的特定 join-operator 和 join-constraint 。
所有 SQLite 中的连接都基于左右数据集的笛卡尔积。笛卡尔积数据集的列按顺序为左手数据集的所有列,然后是右手数据集的所有列。通过组合左手和右手数据集中的每一行唯一组合,笛卡尔积数据集中形成一行。换句话说,如果左手数据集由Nleft 行Mleft 列组成,而右手数据集由Nright 行Mright 列组成,则笛卡尔积是一个Nleft ×Nright 行的数据集,每一行包含Mleft +Mright 列。
如果 join-operator 是“CROSS JOIN”、“INNER JOIN”、“JOIN”或逗号(“,”),并且没有 ON 或 USING 子句,则连接的结果只是左手和右手数据集的笛卡尔积。如果 join-operator 确实有 ON 或 USING 子句,则根据以下要点处理它们
如果有 ON 子句,则 ON 表达式将对笛卡尔积的每一行作为 布尔表达式 进行计算。只有表达式计算结果为真的行才包含在数据集中。
如果有 USING 子句,则必须在 join-operator 左侧和右侧的数据集中存在每个指定的列名。对于每一对命名列,表达式“lhs.X = rhs.X”将对笛卡尔积的每一行作为 布尔表达式 进行计算。只有所有此类表达式计算结果都为真的行才包含在结果集中。在比较值作为 USING 子句的结果时,将应用处理亲和性、排序规则和 NULL 值在比较中的正常规则。出于排序规则和亲和性优先级的目的,join-operator 左侧数据集中的列被视为比较运算符(=)的左侧。
对于由 USING 子句标识的每一对列,将从连接数据集中省略来自右手数据集的列。这是 USING 子句与其等效 ON 约束之间的唯一区别。
如果 join-operator 中包含 NATURAL 关键字,则将隐式 USING 子句添加到 join-constraints 中。隐式 USING 子句包含出现在左手和右手输入数据集中的每个列名。如果左手和右手输入数据集没有公共列名,则 NATURAL 关键字对连接的结果没有影响。不能将 USING 或 ON 子句添加到指定 NATURAL 关键字的连接中。
如果 join-operator 是“LEFT JOIN”或“LEFT OUTER JOIN”,则在应用 ON 或 USING 过滤子句后,将为原始左手输入数据集中与右手数据集中的任何行都不匹配的每一行添加额外的一行输出。添加的行在通常包含从右手输入数据集复制的值的列中包含 NULL 值。
如果 join-operator 是“RIGHT JOIN”或“RIGHT OUTER JOIN”,则在应用 ON 或 USING 过滤子句后,将为原始右手输入数据集中与左手数据集中的任何行都不匹配的每一行添加额外的一行输出。添加的行在通常包含从左手输入数据集复制的值的列中包含 NULL 值。
“FULL JOIN”或“FULL OUTER JOIN”是“LEFT JOIN”和“RIGHT JOIN”的组合。将为左侧数据集中与右侧数据集中没有行匹配的每一行添加额外的输出行,以及为右侧数据集中与左侧数据集中没有行匹配的每一行添加额外的输出行。不匹配的列将填充为 NULL。
当多个表作为 FROM 子句的一部分连接在一起时,连接操作将按从左到右的顺序处理。换句话说,FROM 子句(A join-op-1 B join-op-2 C)计算为((A join-op-1 B)join-op-2 C)。
2.2. CROSS JOIN 的特殊处理。
“INNER JOIN”、“JOIN”和“,”连接运算符之间没有区别。它们在 SQLite 中完全可以互换。“CROSS JOIN”连接运算符产生的结果与“INNER JOIN”、“JOIN”和“,”运算符相同,但查询优化器处理方式不同 ,因为它阻止查询优化器重新排序连接中的表。应用程序程序员可以使用 CROSS JOIN 运算符直接影响用于实现 SELECT 语句的算法。除非在需要手动控制查询优化器的特定情况下,否则避免使用 CROSS JOIN。在应用程序开发的早期避免使用 CROSS JOIN,因为这样做是过早优化 。CROSS JOIN 的特殊处理是 SQLite 特定的功能,而不是标准 SQL 的一部分。
2.3. WHERE 子句过滤。
如果指定了 WHERE 子句,则 WHERE 表达式将对输入数据中的每一行作为 布尔表达式 进行计算。只有 WHERE 子句表达式计算结果为真的行才会包含在数据集中,然后再继续。如果 WHERE 子句计算结果为假或 NULL,则将行从结果中排除。
对于 JOIN、INNER JOIN 或 CROSS JOIN,WHERE 子句中的约束表达式与 ON 子句中的约束表达式之间没有区别。但是,对于 LEFT、RIGHT 或 FULL OUTER JOIN,差异非常重要。在外连接中,对于另一个操作数上不匹配的行,额外的 NULL 行是在 ON 子句处理之后但 WHERE 子句处理之前添加的。因此,ON 子句中形如“left.x=right.y”的约束将允许所有 NULL 行通过。但是,如果相同的约束在 WHERE 子句中,则“right.y”或“left.x”中的 NULL 将阻止表达式“left.x=right.y”为真,从而将该行排除在输出之外。
2.4. 结果行集的生成
一旦来自 FROM 子句的输入数据(如果有)被 WHERE 子句表达式过滤,则计算简单 SELECT 的结果行集。具体如何执行取决于简单 SELECT 是聚合查询还是非聚合查询,以及是否指定了 GROUP BY 子句。
SELECT 和 FROM 关键字之间的表达式列表称为结果表达式列表。如果结果表达式是特殊表达式“*”,则将输入数据中的所有列替换为该表达式。如果表达式是 FROM 子句中表或子查询的别名后跟“.*”,则将命名表或子查询中的所有列替换为单个表达式。在结果表达式列表以外的任何上下文中使用“*”或“alias.*”表达式都是错误的。在没有 FROM 子句的简单 SELECT 查询中使用“*”或“alias.*”表达式也是错误的。
简单 SELECT 语句返回的行中的列数等于替换 * 和 alias.* 表达式后的结果表达式列表中的表达式数。每个结果行都是通过针对输入数据的单个行(或对于聚合查询,针对一组行)计算结果表达式列表中的表达式来计算的。
如果 SELECT 语句是非聚合查询 ,则对 WHERE 子句过滤的数据集中的每一行计算结果表达式列表中的每个表达式。
如果 SELECT 语句是没有 GROUP BY 子句的聚合查询 ,则对整个数据集计算结果集中每个聚合表达式一次。对数据集的任意选择的一行计算结果集中每个非聚合表达式一次。对于每个非聚合表达式,使用相同的任意选择的行。或者,如果数据集包含零行,则针对完全由 NULL 值组成的行计算每个非聚合表达式。
通过计算结果集中聚合和非聚合表达式创建的单个结果集数据行构成了没有 GROUP BY 子句的聚合查询的结果。没有 GROUP BY 子句的聚合查询始终返回正好一行数据,即使输入数据为零行也是如此。
如果 SELECT 语句是带有 GROUP BY 子句的聚合查询 ,则根据下面针对 ORDER BY 表达式陈述的处理规则,对数据集的每一行计算 GROUP BY 子句中指定的每个表达式。然后,根据结果将每一行分配给一个“组”;评估 GROUP BY 表达式结果相同的行将分配到同一个组。为了对行进行分组,NULL 值被视为相等。评估 GROUP BY 子句中的表达式时,应用选择排序规则 的常用规则来比较文本值。GROUP BY 子句中的表达式不必 是出现在结果中的表达式。GROUP BY 子句中的表达式不能是聚合表达式。
如果指定了 HAVING 子句,则将其针对每一组行作为布尔表达式 计算一次。如果计算 HAVING 子句的结果为假,则丢弃该组。如果 HAVING 子句是聚合表达式,则在该组中的所有行上计算它。如果 HAVING 子句是非聚合表达式,则针对从该组中任意选择的一行计算它。HAVING 表达式可以引用值(甚至聚合函数),即使这些值不在结果中。
然后,对每一组行计算结果集中的每个表达式一次。如果表达式是聚合表达式,则在该组中的所有行上计算它。否则,针对该组内任意选择的一行计算它。如果结果集中有多个非聚合表达式,则对同一行计算所有这些表达式。
输入数据集行的每一组都为结果行集贡献一行。根据与 DISTINCT 关键字相关的过滤,带有 GROUP BY 子句的聚合查询返回的行数与通过将 GROUP BY 和 HAVING 子句应用于过滤后的输入数据集生成的组数相同。
2.5. 聚合查询中的裸列
通常情况下,聚合查询中的所有列名要么是聚合函数 的参数,要么出现在 GROUP BY 子句中。包含不在聚合函数内且未出现在 GROUP BY 子句(如果存在)中的列名的结果列称为“裸”列。示例
SELECT a, b, sum(c) FROM tab1 GROUP BY a;
在上面的查询中,“a”列是 GROUP BY 子句的一部分,因此输出的每一行都包含“a”的一个不同的值。“c”列包含在sum() 聚合函数中,因此该输出列是具有相同“a”值的行中所有“c”值的总和。但是,裸列“b”的结果是什么?答案是“b”结果将是构成聚合的输入行之一中“b”的值。问题在于通常不知道使用哪个输入行来计算“b”,因此在许多情况下,“b”的值是未定义的。
当聚合函数为min() 或max() 时,会发生特殊处理。示例
SELECT a, b, max(c) FROM tab1 GROUP BY a;
如果查询中正好有一个min() 或max() 聚合,则结果集中所有裸列都取自也包含最小值或最大值的输入行。因此,在上面的查询中,输出中“b”列的值将是具有最大“c”值的输入行中“b”列的值。min() 和max() 的这种特殊行为存在一些限制
如果相同最小值或最大值出现在两行或多行上,则可能会从这些行中的任何一行选择裸值。选择是任意的。无法预测将从哪一行选择裸值。对于同一查询内的不同裸列,选择可能不同。
如果查询中存在两个或多个min() 或max() 聚合,则裸列值将取自其中一个聚合具有其最小值或最大值的行的其中一行。确定哪个min() 或max() 聚合决定裸列值的选取是任意的。对于同一查询内的不同裸列,选择可能不同。
这种针对min() 或max() 聚合的特殊处理仅适用于这些聚合的内置实现。如果应用程序使用应用程序定义的替代项覆盖内置min() 或max() 聚合,则将从任意行中获取为裸列选择的值。
大多数其他 SQL 数据库引擎不允许使用裸列。如果在查询中包含裸列,其他数据库引擎通常会引发错误。能够在查询中包含裸列是 SQLite 特定的扩展。这被认为是一个特性,而不是一个错误。有关更多信息,请参阅SQLite 论坛主题 7481d2a6df8980ff 中的讨论。
2.6. 删除重复行(DISTINCT 处理)
在简单 SELECT 语句中,SELECT 关键字后面可以跟随 ALL 或 DISTINCT 关键字之一。如果简单 SELECT 是 SELECT ALL,则 SELECT 返回结果行的整个集合。如果没有 ALL 或 DISTINCT,则行为就像指定了 ALL 一样。如果简单 SELECT 是 SELECT DISTINCT,则在返回结果行集之前,将从中删除重复行。为了检测重复行,两个 NULL 值被视为相等。应用常用规则 来选择排序规则以比较文本值。
3. 复合 SELECT 语句
可以使用 UNION、UNION ALL、INTERSECT 或 EXCEPT 运算符将两个或多个简单 SELECT 语句连接在一起以形成复合 SELECT,如下面的图表所示
复合-select-stmt
隐藏
WITH
RECURSIVE
common-table-expression
,
select-core
ORDER
BY
LIMIT
expr
UNION
UNION
ALL
select-core
INTERSECT
EXCEPT
ordering-term
,
OFFSET
expr
,
expr
common-table-expression
显示
table-name
(
column-name
)
AS
NOT
MATERIALIZED
(
select-stmt
)
,
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
compound-operator
显示
UNION
UNION
INTERSECT
EXCEPT
ALL
join-clause
显示
table-or-subquery
join-operator
table-or-subquery
join-constraint
join-constraint
显示
USING
(
column-name
)
,
ON
expr
join-operator
显示
NATURAL
LEFT
OUTER
JOIN
,
RIGHT
FULL
INNER
CROSS
result-column
显示
expr
AS
column-alias
*
table-name
.
*
table-or-subquery
显示
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
window-defn
显示
(
base-window-name
PARTITION
BY
expr
,
ORDER
BY
ordering-term
,
frame-spec
)
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
显示
literal-value
bind-parameter
schema-name
.
table-name
.
column-name
unary-operator
expr
expr
binary-operator
expr
function-name
(
function-arguments
)
filter-clause
over-clause
(
expr
)
,
CAST
(
expr
AS
type-name
)
expr
COLLATE
collation-name
expr
NOT
LIKE
GLOB
REGEXP
MATCH
expr
expr
ESCAPE
expr
expr
ISNULL
NOTNULL
NOT
NULL
expr
IS
NOT
DISTINCT
FROM
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
filter-clause
显示
function-arguments
显示
DISTINCT
expr
,
*
ORDER
BY
ordering-term
,
literal-value
显示
CURRENT_TIMESTAMP
numeric-literal
string-literal
blob-literal
NULL
TRUE
FALSE
CURRENT_TIME
CURRENT_DATE
over-clause
显示
OVER
window-name
(
base-window-name
PARTITION
BY
expr
,
ORDER
BY
ordering-term
,
frame-spec
)
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-function
显示
RAISE
(
ROLLBACK
,
error-message
)
IGNORE
ABORT
FAIL
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
compound-operator
显示
UNION
UNION
INTERSECT
EXCEPT
ALL
join-clause
显示
table-or-subquery
join-operator
table-or-subquery
join-constraint
join-constraint
显示
USING
(
column-name
)
,
ON
expr
join-operator
显示
NATURAL
LEFT
OUTER
JOIN
,
RIGHT
FULL
INNER
CROSS
result-column
显示
expr
AS
column-alias
*
table-name
.
*
table-or-subquery
显示
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
window-defn
显示
(
base-window-name
PARTITION
BY
expr
,
ORDER
BY
ordering-term
,
frame-spec
)
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
type-name
显示
name
(
signed-number
,
signed-number
)
(
signed-number
)
signed-number
显示
ordering-term
显示
expr
COLLATE
collation-name
DESC
ASC
NULLS
FIRST
NULLS
LAST
select-core
显示
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
)
,
,
join-clause
显示
table-or-subquery
join-operator
table-or-subquery
join-constraint
join-constraint
显示
USING
(
column-name
)
,
ON
expr
join-operator
显示
NATURAL
LEFT
OUTER
JOIN
,
RIGHT
FULL
INNER
CROSS
result-column
显示
expr
AS
column-alias
*
table-name
.
*
table-or-subquery
显示
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
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
compound-operator
显示
UNION
UNION
INTERSECT
EXCEPT
ALL
window-defn
显示
(
base-window-name
PARTITION
BY
expr
,
ORDER
BY
ordering-term
,
frame-spec
)
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
在复合 SELECT 中,所有组成 SELECT 必须返回相同数量的结果列。由于复合 SELECT 的组件必须是简单 SELECT 语句,因此它们不能包含ORDER BY 或LIMIT 子句。ORDER BY 和LIMIT 子句只能出现在整个复合 SELECT 的末尾,并且仅当复合的最后一个元素不是VALUES 子句时。
使用 UNION ALL 运算符创建的复合 SELECT 返回 UNION ALL 运算符左侧 SELECT 的所有行,以及右侧 SELECT 的所有行。UNION 运算符的工作方式与 UNION ALL 相同,只是最终结果集中删除了重复行。INTERSECT 运算符返回左侧和右侧 SELECT 结果的交集。EXCEPT 运算符返回左侧 SELECT 返回的行子集,这些行不是右侧 SELECT 也返回的行。在返回结果集之前,将从 INTERSECT 和 EXCEPT 运算符的结果中删除重复行。
为了确定复合 SELECT 运算符结果的重复行,NULL 值被视为等于其他 NULL 值,并且不同于所有非 NULL 值。用于比较两个文本值的排序规则的确定方式,就像左侧和右侧 SELECT 语句的列是等于 (=) 运算符的左侧和右侧操作数一样,只是不为后缀 COLLATE 运算符指定的排序规则分配更高的优先级。在将行作为复合 SELECT 的一部分进行比较时,不会对任何值应用亲和性转换。
当三个或更多简单 SELECT 连接到复合 SELECT 中时,它们从左到右分组。换句话说,如果“A”、“B”和“C”都是简单 SELECT 语句,则 (A op B op C) 将被处理为 ((A op B) op C) 。
4. ORDER BY 子句
如果返回多行的 SELECT 语句没有 ORDER BY 子句,则返回行的顺序未定义。或者,如果 SELECT 语句确实具有 ORDER BY 子句,则附加到 ORDER BY 的表达式列表确定返回给用户的行的顺序。
在复合 SELECT 语句中,只有最后一个或最右边的简单 SELECT 可以包含 ORDER BY 子句。该 ORDER BY 子句将应用于复合语句的所有元素。如果复合 SELECT 的最右边元素是VALUES 子句,则不允许在该语句上使用 ORDER BY 子句。
行首先根据 ORDER BY 列表中最左侧表达式的计算结果进行排序,然后通过计算第二左侧表达式来解决冲突,依此类推。对于所有 ORDER BY 表达式计算结果都相等的两个行,返回顺序未定义。每个 ORDER BY 表达式之后可以可选地跟 ASC(较小的值先返回)或 DESC(较大的值先返回)关键字之一。如果没有指定 ASC 或 DESC,则默认情况下按升序(较小的值优先)排序。
SQLite 将 NULL 值视为小于任何其他值用于排序目的。因此,NULL 值自然出现在 ASC 排序的开头和 DESC 排序的结尾。这可以通过使用“ASC NULLS LAST”或“DESC NULLS FIRST”语法来更改。
每个 ORDER BY 表达式按如下方式处理
如果 ORDER BY 表达式是常量整数 K,则该表达式被视为结果集第 K 列的别名(列从左到右编号,从 1 开始)。
如果 ORDER BY 表达式是与一个输出列的别名相对应的标识符,则该表达式被视为该列的别名。
否则,如果 ORDER BY 表达式是任何其他表达式,则对其进行计算并使用返回的值来对输出行进行排序。如果 SELECT 语句是简单 SELECT,则 ORDER BY 可以包含任何任意表达式。但是,如果 SELECT 是复合 SELECT,则不是输出列别名的 ORDER BY 表达式必须与用作输出列的表达式完全相同。
为了对行进行排序,值的比较方式与比较表达式 相同。用于比较两个文本值的排序规则如下
如果 ORDER BY 表达式使用后缀COLLATE 运算符 分配了排序规则,则使用指定的排序规则。
否则,如果 ORDER BY 表达式是已使用后缀COLLATE 运算符 分配了排序规则的表达式的别名,则使用分配给该别名表达式的排序规则。
否则,如果 ORDER BY 表达式是列或表达式的别名,而该表达式是列,则使用该列的默认排序规则。
否则,使用BINARY 排序规则。
在复合 SELECT 语句中,所有 ORDER BY 表达式都作为复合语句结果列之一的别名处理。如果 ORDER BY 表达式不是整数别名,则 SQLite 会在复合语句中最左侧的 SELECT 中搜索与上面第二或第三条规则匹配的结果列。如果找到匹配项,则搜索停止,并且该表达式被视为与之匹配的结果列的别名。否则,尝试下一个右侧的 SELECT,依此类推。如果在任何组成 SELECT 的结果列中都找不到匹配的表达式,则为错误。ORDER BY 子句的每个术语都是单独处理的,并且可以与复合语句中不同 SELECT 语句的结果列匹配。
5. LIMIT 子句
LIMIT 子句用于对整个 SELECT 语句返回的行数设置上限。
在复合 SELECT 中,只有最后一个或最右边的简单 SELECT 可以包含 LIMIT 子句。在复合 SELECT 中,LIMIT 子句应用于整个复合语句,而不仅仅是最后的 SELECT。如果最右边的简单 SELECT 是VALUES 子句 ,则不允许使用 LIMIT 子句。
只要 LIMIT 子句中的任何标量表达式计算结果为整数或可以无损转换为整数的值,就可以使用它。如果表达式的计算结果为 NULL 值或任何其他无法无损转换为整数的值,则返回错误。如果 LIMIT 表达式计算结果为负值,则返回的行数没有上限。否则,SELECT 仅返回其结果集的前 N 行,其中 N 是 LIMIT 表达式计算结果的值。或者,如果 SELECT 语句在没有 LIMIT 子句的情况下返回的行数少于 N 行,则返回整个结果集。
附加到可选 OFFSET 子句(可能位于 LIMIT 子句之后)的表达式也必须计算结果为整数,或可以无损转换为整数的值。如果表达式具有 OFFSET 子句,则从 SELECT 语句返回的结果集中省略前 M 行,并返回接下来的 N 行,其中 M 和 N 分别是 OFFSET 和 LIMIT 子句计算结果的值。或者,如果 SELECT 在没有 LIMIT 子句的情况下返回的行数少于 M+N 行,则跳过前 M 行,并返回剩余的行(如果有)。如果 OFFSET 子句计算结果为负值,则结果与计算结果为零相同。
LIMIT 子句可以使用两个用逗号分隔的标量表达式,而不是单独的 OFFSET 子句。在这种情况下,第一个表达式用作 OFFSET 表达式,第二个用作 LIMIT 表达式。这与直觉相反,因为当使用 OFFSET 子句时,两个表达式中的第二个是 OFFSET,第一个是 LIMIT。这种 OFFSET 和 LIMIT 的反转是有意的——它最大程度地与其他 SQL 数据库系统兼容。但是,为了避免混淆,强烈建议程序员使用使用“OFFSET”关键字的 LIMIT 子句的形式,并避免使用带有逗号分隔的偏移量的 LIMIT 子句。
6. VALUES 子句
短语“VALUES(expr-list )”与“SELECT expr-list ”含义相同。短语“VALUES(expr-list-1 ),...,(expr-list-N )”与“SELECT expr-list-1 UNION ALL ... UNION ALL SELECT expr-list-N ”含义相同。这两种形式是相同的,只是复合语句中 SELECT 语句的数量受SQLITE_LIMIT_COMPOUND_SELECT 限制,而 VALUES 子句中的行数没有任意限制。
VALUES 子句的使用有一些限制,在语法图中没有显示
7. WITH 子句
SELECT 语句前面可以可选地加上一个WITH 子句 ,该子句定义一个或多个公用表表达式 供 SELECT 语句中使用。
8. FROM 子句中的表值函数
包含隐藏列 的虚拟表 可以在 FROM 子句中像表值函数 一样使用。表值函数的参数成为虚拟表隐藏列上的约束。更多信息可以在虚拟表文档 中找到。
9. 与标准 SQL 的偏差
SQLite 的 SELECT 语法与标准 SQL 略有不同。这些差异是由于以下几个原因造成的
在 2000 年代中期,人们非常重视保持库占用空间尽可能小,这样就不会在内存受限的翻盖手机等设备上占用太多空间。
在 SQLite 的早期,首席开发人员试图遵循Postel 定律 ,并对接受的输入具有容错性和灵活性。
早期 SQLite 解析器中存在一些错误,这些错误会接受一些奇怪的输入。
首席开发人员对 SQL 的了解并不完善。
无论输入怪癖的来源是什么,我们通常都避免尝试“修复”它们,因为对输入语法的任何新限制都可能导致至少数百万使用 SQLite 的应用程序出现故障。我们不希望这样。SQLite 开发团队的目标是最大程度地保持向后兼容性。因此,如果语法怪癖无害,我们就会保留它并在本文档中记录它,而不是尝试修复它。
9.1. 奇怪的 JOIN 名称
SQLite 接受所有常用的 JOIN 运算符语法
join-operator
隐藏
NATURAL
LEFT
OUTER
JOIN
,
RIGHT
FULL
INNER
CROSS
但它并没有就此止步。SQLite 在指定连接运算符的方式上实际上非常灵活。通用语法为
blah blah blah JOIN
其中“blah ”有 1 到 3 个实例,每个实例可以是“CROSS”、“FULL”、“INNER”、“LEFT”、“NATURAL”、“OUTER”或“RIGHT”中的任何一个。SQLite 解析器将这些关键字中的每一个都视为连接的属性,这些属性可以以任何顺序组合。这创建了在语法图中指定的连接类型之外的许多新的和创造性的连接类型的可能性。其中一些非标准连接类型被明确禁止。例如,您不能说“INNER OUTER JOIN”,因为这将是矛盾的。但是您可以说“OUTER LEFT NATURAL JOIN”,这与“NATURAL LEFT OUTER JOIN”含义相同。或者您可以说“LEFT RIGHT JOIN”,这与“FULL JOIN”相同。
请记住:您可以 使用这些非标准连接类型,但您不应该 。坚持使用标准的 JOIN 语法,以便与其他 SQL 数据库引擎保持可移植性。
9.2. 灵活的连接语法
标准 SQL 对连接语法的限制比 SQLite 严格。在标准 SQL 中,除逗号连接、CROSS JOIN 和 NATURAL 连接之外的所有连接都必须具有 ON 子句或 USING 子句,而逗号连接、CROSS JOIN 和 NATURAL 连接不能同时具有 ON 或 USING 子句。SQLite 对连接语法并不那么挑剔。SQLite 将接受并处理逗号连接或 CROSS JOIN 上的 ON 或 USING 子句,并且允许您从任何连接中省略 ON 或 USING 子句。在 SQLite 中,唯一的限制是
SQLite 甚至允许您从外部连接中省略 ON 或 USING 子句,尽管这样做意味着外部连接不受约束(就像 ON 子句为“ON true ”一样),这使得外部连接的行为类似于内部连接。
9.3. 逗号连接和 CROSS JOIN 的优先级
在标准 SQL 中,使用 JOIN 关键字的连接优先于逗号连接。也就是说,JOIN 运算符先于逗号运算符发生。在 SQLite 中并非如此,所有连接的优先级都相同。
考虑以下示例
... FROM t1, t2 NATURAL FULL JOIN t3 ...
在标准 SQL 中,t2 和 t3 之间的 FULL JOIN 将首先发生,然后左连接的结果将与 t1 进行交叉连接。但是 SQLite 始终从左到右处理所有连接。因此,SQLite 将首先对 t1 和 t2 进行交叉连接,然后将该交叉连接的结果馈送到与 t3 的 FULL JOIN 中。内部连接本质上是关联的,因此只有当您的 FROM 子句包含一个或多个外部连接时,差异才会显现。
您可以解决此问题,并使您的 SQL 语句在所有系统上都可移植,方法是遵守以下样式规则
任何一条建议都足以避免问题,并且大多数程序员会本能地遵循所有这些建议而无需被告知,因此逗号连接和 JOIN 关键字在 SQLite 中缺乏优先级差异在实践中很少出现。但是,您应该意识到这个问题,以防它出现。
此页面最后修改于 2024-05-11 12:18:17 UTC