SELECT
[ALL | DISTINCT | DISTINCTROW ]
[HIGH_PRIORITY]
[STRAIGHT_JOIN]
[SQL_SMALL_RESULT] [SQL_BIG_RESULT] [SQL_BUFFER_RESULT]
[SQL_NO_CACHE] [SQL_CALC_FOUND_ROWS]
select_expr [, select_expr] ...
[into_option]
[FROM table_references
[PARTITION partition_list]]
[WHERE where_condition]
[GROUP BY {col_name | expr | position}, ... [WITH ROLLUP]]
[HAVING where_condition]
[WINDOW window_name AS (window_spec)
[, window_name AS (window_spec)] ...]
[ORDER BY {col_name | expr | position}
[ASC | DESC], ... [WITH ROLLUP]]
[LIMIT {[offset,] row_count | row_count OFFSET offset}]
[into_option]
[FOR {UPDATE | SHARE}
[OF tbl_name [, tbl_name] ...]
[NOWAIT | SKIP LOCKED]
| LOCK IN SHARE MODE]
[into_option]
into_option: {
INTO OUTFILE 'file_name'
[CHARACTER SET charset_name]
export_options
| INTO DUMPFILE 'file_name'
| INTO var_name [, var_name] ...
}
SELECT
用于检索从一个或多个表中选择的行,并且可以包括
UNION
操作和子查询。从MySQL 8.0.31开始,
INTERSECT
也
EXCEPT
支持操作。、UNION
和
运算符将在本节后面进行更详细的描述INTERSECT
。EXCEPT
另见第 13.2.11 节,“子查询”。
SELECT
语句可以以子句开头,
以WITH
定义可在
SELECT
. 请参阅第 13.2.15 节,“WITH(公用表表达式)”。
最常用的
SELECT
语句子句是:
每个都
select_expr
表示您要检索的列。必须至少有一个select_expr
。table_references
指示要从中检索行的一个或多个表。它的语法在第 13.2.10.2 节,“JOIN 子句”中描述。SELECT
PARTITION
支持使用带有分区列表或子分区(或两者) 的子句的显式分区选择,这些子句跟在 a 中的表名之后table_reference
(请参阅 第 13.2.10.2 节,“JOIN 子句”)。在这种情况下,仅从列出的分区中选择行,而忽略表的任何其他分区。有关更多信息和示例,请参阅 第 24.5 节,“分区选择”。该
WHERE
子句(如果给定)指示要选择行必须满足的一个或多个条件。where_condition
是一个表达式,对于要选择的每一行计算结果为真。如果没有WHERE
子句,该语句将选择所有行。在
WHERE
表达式中,您可以使用 MySQL 支持的任何函数和运算符,但聚合(组)函数除外。请参阅 第 9.5 节,“表达式”和 第 12 章,函数和运算符。
SELECT
也可用于检索在未引用任何表的情况下计算的行。
例如:
mysql> SELECT 1 + 1;
-> 2
mysql> SELECT 1 + 1 FROM DUAL;
-> 2
DUAL
纯粹是为了方便那些要求所有SELECT
语句都应该有FROM
并且可能还有其他子句的人。MySQL 可能会忽略这些子句。FROM DUAL
如果没有引用表,则
MySQL 不需要
。
通常,使用的子句必须完全按照语法描述中显示的顺序给出。例如,
HAVING
子句必须位于任何子句之后
GROUP BY
和任何子句之前ORDER
BY
。该INTO
子句(如果存在)可以出现在语法描述指示的任何位置,但在给定语句中只能出现一次,不能出现在多个位置。有关 的更多信息
INTO
,请参阅第 13.2.10.1 节,“SELECT ... INTO 语句”。
术语列表select_expr
包含指示要检索哪些列的选择列表。术语指定列或表达式,或者可以使用
*
-shorthand:
只包含一个非限定的选择列表
*
可以用作从所有表中选择所有列的速记:SELECT * FROM t1 INNER JOIN t2 ...
可以用作限定速记来从命名表中选择所有列:tbl_name
.*SELECT t1.*, t2.* FROM t1 INNER JOIN t2 ...
如果一个表有不可见的列,
*
不要
包含它们。要包含在内,必须明确引用不可见的列。tbl_name
.*对选择列表中的其他项目使用不合格
*
可能会产生分析错误。例如:SELECT id, * FROM t1
为避免此问题,请使用合格的
参考:tbl_name
.*SELECT id, t1.* FROM t1
对选择列表中的每个表 使用限定 引用:tbl_name
.*SELECT AVG(score), t1.* FROM t1 ...
以下列表提供了有关其他
SELECT
条款的附加信息:
select_expr
可以使用 给 A一个别名。别名用作表达式的列名,可用于 、或 子句中。例如:AS
alias_name
GROUP BY
ORDER BY
HAVING
SELECT CONCAT(last_name,', ',first_name) AS full_name FROM mytable ORDER BY full_name;
当使用标识符为 a 别名时, 该
AS
关键字是可选 的。select_expr
前面的例子可以这样写:SELECT CONCAT(last_name,', ',first_name) full_name FROM mytable ORDER BY full_name;
然而,因为
AS
是可选的,如果您忘记了两个select_expr
表达式之间的逗号,就会出现一个微妙的问题:MySQL 将第二个解释为别名。例如,在以下语句中,columnb
被视为别名:SELECT columna columnb FROM mytable;
AS
出于这个原因,在指定列别名时养成显式 使用的习惯是很好的做法。不允许在子句中引用列别名
WHERE
,因为在执行子句时列值可能尚未确定WHERE
。请参阅第 B.3.4.4 节,“列别名的问题”。该子句指示要从中检索行的一个或多个表。如果您命名多个表,则您正在执行连接。有关连接语法的信息,请参阅第 13.2.10.2 节,“JOIN 子句”。对于每个指定的表,您可以选择指定一个别名。
FROM
table_references
tbl_name [[AS] alias] [index_hint]
索引提示的使用为优化器提供了有关如何在查询处理期间选择索引的信息。有关指定这些提示的语法的描述,请参阅 第 8.9.4 节,“索引提示”。
您可以使用 另一种方法来强制 MySQL 更喜欢键扫描而不是表扫描。请参阅 第 5.1.8 节,“服务器系统变量”。
SET max_seeks_for_key=
value
您可以将默认数据库中的表引用为
tbl_name
或db_name
。tbl_name
明确指定数据库。您可以将列称为col_name
,tbl_name
。col_name
, 或者db_name
.tbl_name
.col_name
. 您无需指定tbl_name
或db_name
。tbl_name
列引用的前缀,除非引用不明确。有关需要更明确的列引用形式的歧义示例, 请参见第 9.2.2 节,“标识符限定符” 。可以使用 或 为表引用起别名。这些语句是等价的:
tbl_name
ASalias_name
tbl_name alias_name
SELECT t1.name, t2.salary FROM employee AS t1, info AS t2 WHERE t1.name = t2.name; SELECT t1.name, t2.salary FROM employee t1, info t2 WHERE t1.name = t2.name;
可以使用列名、列别名或列位置在
ORDER BY
和子句 中引用为输出选择的 列。GROUP BY
列位置是整数并以 1 开头:SELECT college, region, seed FROM tournament ORDER BY region, seed; SELECT college, region AS r, seed AS s FROM tournament ORDER BY r, s; SELECT college, region, seed FROM tournament ORDER BY 2, 3;
要以相反的顺序排序,请将(降序)关键字添加到您作为排序依据
DESC
的子句中的列的名称 。ORDER BY
默认为升序;这可以使用ASC
关键字明确指定。如果
ORDER BY
出现在带括号的查询表达式中并且也应用于外部查询,则结果是未定义的,并且可能会在未来版本的 MySQL 中发生变化。不推荐使用列位置,因为该语法已从 SQL 标准中删除。
在 MySQL 8.0.13 之前,MySQL 支持非标准语法扩展,允许显式
ASC
或 列DESC
指示符GROUP BY
。MySQL 8.0.12及以后版本支持ORDER BY
with分组功能,不再需要使用该扩展。(Bug #86312,Bug #26073525)这也意味着您可以在使用时对任意一列或多列进行排序GROUP BY
,如下所示:SELECT a, b, COUNT(c) AS t FROM test_table GROUP BY a,b ORDER BY a,t DESC;
从 MySQL 8.0.13 开始,
GROUP BY
不再支持扩展:ASC
或者 不允许列的DESC
指示符。GROUP BY
当您使用
ORDER BY
或GROUP BY
对 a 中的列进行排序时 ,服务器仅使用系统变量SELECT
指示的初始字节数对值进行排序 。max_sort_length
MySQL 扩展了使用以允许选择子句
GROUP BY
中未提及的字段。GROUP BY
如果您没有从查询中获得预期的结果,请阅读 第 12.20 节“聚合函数”GROUP BY
中 的说明。GROUP BY
允许WITH ROLLUP
修饰符。请参阅 第 12.20.2 节,“GROUP BY 修饰符”。以前,不允许
ORDER BY
在具有WITH ROLLUP
修饰符的查询中使用。这个限制从 MySQL 8.0.12 开始解除。请参阅第 12.20.2 节,“GROUP BY 修饰符”。该
HAVING
子句与WHERE
子句一样,指定选择条件。该WHERE
子句指定选择列表中列的条件,但不能引用聚合函数。该HAVING
子句指定组的条件,通常由该GROUP BY
子句构成。查询结果只包含满足HAVING
条件的组。(如果不GROUP BY
存在,所有行隐含地形成一个聚合组。)该
HAVING
子句几乎最后应用,就在项目发送给客户端之前,没有优化。(LIMIT
在 之后应用HAVING
。)SQL 标准要求
HAVING
必须仅引用GROUP BY
子句中的列或聚合函数中使用的列。但是,MySQL 支持对此行为的扩展,并允许HAVING
引用列表中的SELECT
列和外部子查询中的列。如果
HAVING
子句引用的列不明确,则会出现警告。在以下语句中,col2
是不明确的,因为它既用作别名又用作列名:SELECT COUNT(col1) AS col2 FROM t GROUP BY col2 HAVING col2 = 2;
优先考虑标准 SQL 行为,因此如果 在选择列列表
HAVING
中同时使用列名称GROUP BY
和作为别名列,则优先考虑列中的GROUP BY
列。不要
HAVING
用于应该在WHERE
子句中的项目。例如,不要写以下内容:SELECT col_name FROM tbl_name HAVING col_name > 0;
改为这样写:
SELECT col_name FROM tbl_name WHERE col_name > 0;
该
HAVING
子句可以引用聚合函数,但该WHERE
子句不能:SELECT user, MAX(salary) FROM users GROUP BY user HAVING MAX(salary) > 10;
(这在某些旧版本的 MySQL 中不起作用。)
MySQL 允许重复的列名。也就是说,可以有多个
select_expr
同名的。这是对标准 SQL 的扩展。因为 MySQL 也允许GROUP BY
和HAVING
引用select_expr
值,这会导致歧义:SELECT 12 AS a, a FROM t GROUP BY a;
在该语句中,两列的名称都是
a
. 为确保使用正确的列进行分组,请为每个使用不同的名称select_expr
。该
WINDOW
子句(如果存在)定义可由窗口函数引用的命名窗口。有关详细信息,请参阅第 12.21.4 节,“命名窗口”。ORDER BY
MySQL通过在select_expr
值中搜索,然后在子句中的表的列中搜索来 解析子句中的不合格列或别名引用FROM
。对于GROUP BY
orHAVING
子句,它在搜索 值FROM
之前先搜索子句。select_expr
(对于GROUP BY
和HAVING
,这不同于使用与 for 相同规则的 MySQL 5.0 之前的行为ORDER BY
。)该
LIMIT
子句可用于限制SELECT
语句返回的行数。LIMIT
接受一个或两个数字参数,它们必须都是非负整数常量,但以下情况除外:在准备好的语句中,
LIMIT
可以使用?
占位符标记指定参数。在存储的程序中,
LIMIT
可以使用整数值例程参数或局部变量来指定参数。
有两个参数,第一个参数指定要返回的第一行的偏移量,第二个参数指定要返回的最大行数。初始行的偏移量为 0(不是 1):
SELECT * FROM tbl LIMIT 5,10; # Retrieve rows 6-15
要检索从某个偏移量到结果集末尾的所有行,您可以为第二个参数使用一些较大的数字。此语句检索从第 96 行到最后一行的所有行:
SELECT * FROM tbl LIMIT 95,18446744073709551615;
使用一个参数,该值指定从结果集开头返回的行数:
SELECT * FROM tbl LIMIT 5; # Retrieve first 5 rows
换句话说,相当于.
LIMIT
row_count
LIMIT 0,
row_count
对于准备好的语句,您可以使用占位符。以下语句从表中返回一行
tbl
:SET @a=1; PREPARE STMT FROM 'SELECT * FROM tbl LIMIT ?'; EXECUTE STMT USING @a;
以下语句返回表中的第二行到第六行
tbl
:SET @skip=1; SET @numrows=5; PREPARE STMT FROM 'SELECT * FROM tbl LIMIT ?, ?'; EXECUTE STMT USING @skip, @numrows;
为了与 PostgreSQL 兼容,MySQL 也支持该 语法。
LIMIT
row_count
OFFSEToffset
如果
LIMIT
出现在带括号的查询表达式中并且也应用于外部查询,则结果是未定义的,并且可能会在未来版本的 MySQL 中发生变化。的
SELECT ... INTO
形式SELECT
使查询结果可以写入文件或存储在变量中。有关详细信息,请参阅 第 13.2.10.1 节,“SELECT ... INTO 语句”。如果
FOR UPDATE
与使用页锁或行锁的存储引擎一起使用,则查询检查的行将被写锁定,直到当前事务结束。您不能将
FOR UPDATE
用作语句的一部分,SELECT
例如 . (如果您尝试这样做,该语句将被拒绝并显示错误 Can't update table ' ' while ' ' is being created。)CREATE TABLE
new_table
SELECT ... FROMold_table
...old_table
new_table
FOR SHARE
并LOCK IN SHARE MODE
设置允许其他事务读取检查的行但不允许更新或删除它们的共享锁。FOR SHARE
并且LOCK IN SHARE MODE
是等价的。但是,FOR SHARE
与 一样FOR UPDATE
,支持NOWAIT
、SKIP LOCKED
和 选项。是 的替代品 ,但仍可用于向后兼容。OF
tbl_name
FOR SHARE
LOCK IN SHARE MODE
LOCK IN SHARE MODE
NOWAIT
导致FOR UPDATE
orFOR SHARE
查询立即执行,如果由于另一个事务持有锁而无法获得行锁,则返回错误。SKIP LOCKED
导致FOR UPDATE
orFOR SHARE
查询立即执行,排除结果集中被另一个事务锁定的行。NOWAIT
和SKIP LOCKED
选项对于基于语句的复制是不安全的。笔记跳过锁定行的查询返回不一致的数据视图。
SKIP LOCKED
因此不适合一般事务性工作。但是,当多个会话访问同一个类似队列的表时,它可用于避免锁争用。OF
对命名表 应用tbl_name
FOR UPDATE
和查询。FOR SHARE
例如:SELECT * FROM t1, t2 FOR SHARE OF t1 FOR UPDATE OF t2;
省略 时,查询块引用的所有表都将被锁定 。因此, 在不与另一个锁定子句组合的情况下使用锁定子句会返回错误。在多个锁定子句中指定同一个表会返回错误。如果在语句中将别名指定为表名,则 锁定子句只能使用别名。如果语句没有明确指定别名,锁定子句可能只指定实际的表名。
OF
tbl_name
OF
tbl_name
SELECT
SELECT
有关
FOR UPDATE
和 的更多信息FOR SHARE
,请参阅 第 15.7.2.4 节,“锁定读取”。有关其他信息NOWAIT
和SKIP LOCKED
选项,请 参阅使用 NOWAIT 和 SKIP LOCKED 锁定读取并发。
在SELECT
关键字之后,您可以使用一些影响语句操作的修饰符。HIGH_PRIORITY
、
STRAIGHT_JOIN
和以开头的修饰符
SQL_
是 MySQL 对标准 SQL 的扩展。
和 修饰符指定是否应返回重复行
ALL
。(默认值)指定应返回所有匹配行,包括重复项。 指定从结果集中删除重复行。同时指定两个修饰符是错误的。是的同义词 。DISTINCT
ALL
DISTINCT
DISTINCTROW
DISTINCT
在 MySQL 8.0.12 及更高版本中,
DISTINCT
可以与也使用WITH ROLLUP
. (漏洞 #87450,漏洞 #26640100)HIGH_PRIORITY
SELECT
比更新表的语句具有更高的 优先级。您应该仅将此用于非常快且必须立即完成的查询。SELECT HIGH_PRIORITY
即使有更新语句等待表释放,在表被锁定以供读取时发出的 查询也会运行。这只会影响仅使用表级锁定的存储引擎(例如MyISAM
、MEMORY
和MERGE
)。STRAIGHT_JOIN
强制优化器按照它们在FROM
子句中列出的顺序连接表。如果优化器以非最佳顺序连接表,您可以使用它来加速查询。STRAIGHT_JOIN
也可以用在table_references
列表中。请参阅 第 13.2.10.2 节,“JOIN 子句”。STRAIGHT_JOIN
不适用于优化器视为const
或 表的任何system
表。这样的表产生单行,在查询执行的优化阶段被读取,并且在查询执行继续之前对其列的引用被替换为适当的列值。这些表最先出现在 显示的查询计划中EXPLAIN
。请参阅 第 8.8.1 节,“使用 EXPLAIN 优化查询”。此例外可能不适用于在外部联接的 - 补充侧使用的const
或system
表(即, a 的右侧表或 a 的左侧表)。NULL
LEFT JOIN
RIGHT JOIN
SQL_BIG_RESULT
orSQL_SMALL_RESULT
可以与GROUP BY
orDISTINCT
一起使用,分别告诉优化器结果集有很多行或很小。对于,如果创建了基于磁盘的临时表,则 MySQL 会直接使用它们,并且更喜欢使用元素SQL_BIG_RESULT
上带有键的临时表进行排序。GROUP BY
对于SQL_SMALL_RESULT
,MySQL 使用内存中的临时表来存储结果表,而不是使用排序。这通常不需要。SQL_BUFFER_RESULT
强制将结果放入临时表中。这有助于 MySQL 尽早释放表锁,并在需要很长时间才能将结果集发送到客户端的情况下提供帮助。该修饰符只能用于顶级SELECT
语句,不能用于子查询或后续UNION
。SQL_CALC_FOUND_ROWS
告诉 MySQL 计算结果集中有多少行,忽略任何LIMIT
子句。然后可以使用 检索行数SELECT FOUND_ROWS()
。请参阅 第 12.16 节,“信息功能”。笔记从 MySQL 8.0.17 开始,不推荐使用
SQL_CALC_FOUND_ROWS
查询修饰符和伴随函数;FOUND_ROWS()
希望它们在未来版本的 MySQL 中被删除。FOUND_ROWS()
有关替代策略的信息, 请参阅 说明。SQL_CACHE
和 修饰符 在SQL_NO_CACHE
MySQL 8.0 之前与查询缓存一起使用。MySQL 8.0 中删除了查询缓存。修改器SQL_CACHE
也被删除了。SQL_NO_CACHE
已弃用,无效;希望在未来的 MySQL 版本中将其删除。