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
操作和子查询。还支持 INTERSECT
和 EXCEPT
操作。UNION
、INTERSECT
和 EXCEPT
运算符将在本节后面详细介绍。另见 第 15.2.15 节“子查询”。
SELECT
语句可以以 WITH
子句开头,以定义可在 SELECT
中访问的公用表表达式。见 第 15.2.20 节“WITH (公用表表达式)”。
SELECT
语句最常用的子句如下:
每个
select_expr
表示要检索的列。必须至少有一个select_expr
。table_references
指示从中检索行的表。其语法在第 15.2.13.2 节,“JOIN 子句”中描述。SELECT
支持使用PARTITION
子句进行显式分区选择,该子句后跟table_reference
中表名后的分区或子分区(或两者)列表(请参阅第 15.2.13.2 节,“JOIN 子句”)。在这种情况下,仅从列出的分区中选择行,并且忽略该表的任何其他分区。有关更多信息和示例,请参阅第 26.5 节,“分区选择”。WHERE
子句(如果给出)指示行必须满足才能被选中的条件。where_condition
是一个表达式,对于要选择的每一行,该表达式的计算结果均为 true。如果没有WHERE
子句,则该语句将选择所有行。在
WHERE
表达式中,可以使用 MySQL 支持的任何函数和运算符,但聚合(分组)函数除外。请参阅第 11.5 节,“表达式”和第 14 章,*函数和运算符*。
SELECT
也可以用于检索在不参考任何表的情况下计算的行。
例如:
mysql> SELECT 1 + 1;
-> 2
在没有引用任何表的情况下,允许您将 DUAL
指定为虚拟表名。
mysql> SELECT 1 + 1 FROM DUAL;
-> 2
DUAL
纯粹是为了方便那些要求所有 SELECT
语句都应该具有 FROM
和其他子句的人。MySQL 可能会忽略这些子句。如果没有引用任何表,则 MySQL 不需要 FROM DUAL
。
通常,必须严格按照语法说明中显示的顺序给出所使用的子句。例如,HAVING
子句必须出现在任何 GROUP BY
子句之后和任何 ORDER BY
子句之前。INTO
子句(如果存在)可以出现在语法说明指示的任何位置,但在给定语句中只能出现一次,而不能出现在多个位置。有关 INTO
的更多信息,请参阅第 15.2.13.1 节,“SELECT ... INTO 语句”。
select_expr
项的列表包含选择列表,该列表指示要检索哪些列。术语指定一个列或表达式,或者可以使用 *
-速记。
仅包含单个非限定
*
的选择列表可以用作速记,以选择所有表中的所有列。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
子句的更多信息。
可以使用
AS
为alias_name
select_expr
指定别名。该别名用作表达式的列名,并且可以在GROUP BY
、ORDER BY
或HAVING
子句中使用。例如:SELECT CONCAT(last_name,', ',first_name) AS full_name FROM mytable ORDER BY full_name;
使用标识符为
select_expr
指定别名时,AS
关键字是可选的。前面的示例可以写成如下形式: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 节,“列别名问题”。FROM
子句指示要从中检索行的表。如果指定了多个表,则表示您正在执行联接。有关联接语法的更多信息,请参阅第 15.2.13.2 节,“JOIN 子句”。对于指定的每个表,您都可以选择指定一个别名。table_references
tbl_name [[AS] alias] [index_hint]
索引提示的使用为优化器提供了有关如何在查询处理期间选择索引的信息。有关指定这些提示的语法说明,请参阅第 10.9.4 节,“索引提示”。
您可以使用
SET max_seeks_for_key=
作为强制 MySQL 首选键扫描而不是表扫描的另一种方法。请参阅第 7.1.8 节,“服务器系统变量”。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
前缀。有关需要更明确的列引用形式的歧义示例,请参阅第 11.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 标准中删除。
当您使用
ORDER BY
或GROUP BY
对SELECT
中的列进行排序时,服务器仅使用max_sort_length
系统变量指示的初始字节数对值进行排序。MySQL 扩展了
GROUP BY
的使用,以允许选择GROUP BY
子句中未提及的字段。如果您没有从查询中获得预期的结果,请阅读第 14.19 节,“聚合函数”中对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
子句(如果存在)定义窗口函数可以引用的命名窗口。有关详细信息,请参阅第 14.20.4 节,“命名窗口”。MySQL 通过在
select_expr
值中搜索,然后在FROM
子句中表的列中搜索,来解析ORDER BY
子句中非限定的列或别名引用。对于GROUP BY
或HAVING
子句,它会在搜索select_expr
值之前先搜索FROM
子句。(对于GROUP BY
和HAVING
,这与 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
使查询结果可以写入文件或存储在变量中。有关更多信息,请参阅 第 15.2.13.1 节,“SELECT ... INTO 语句”。如果将
FOR UPDATE
与使用页面锁或行锁的存储引擎一起使用,则查询检查的行将被写锁定,直到当前事务结束。不能在诸如
CREATE TABLE
的语句中将new_table
SELECT ... FROMold_table
...FOR UPDATE
用作SELECT
的一部分。(如果尝试这样做,该语句将被拒绝,并显示错误 创建“new_table
”时无法更新表“old_table
”。)FOR SHARE
和LOCK IN SHARE MODE
设置共享锁,允许其他事务读取检查的行,但不能更新或删除它们。FOR SHARE
和LOCK IN SHARE MODE
是等效的。但是,与FOR UPDATE
一样,FOR SHARE
也支持NOWAIT
、SKIP LOCKED
和OF
选项。tbl_name
FOR SHARE
是LOCK IN SHARE MODE
的替代品,但为了向后兼容,LOCK IN SHARE MODE
仍然可用。NOWAIT
会导致FOR UPDATE
或FOR SHARE
查询立即执行,如果由于另一个事务持有的锁而无法获取行锁,则返回错误。SKIP LOCKED
会导致FOR UPDATE
或FOR 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
的更多信息,请参阅 第 17.7.2.4 节,“锁定读取”。有关NOWAIT
和SKIP LOCKED
选项的更多信息,请参阅 使用 NOWAIT 和 SKIP LOCKED 锁定读取并发。
在 SELECT
关键字之后,可以使用许多修饰符来影响语句的操作。HIGH_PRIORITY
、STRAIGHT_JOIN
以及以 SQL_
开头的修饰符是 MySQL 对标准 SQL 的扩展。
ALL
和DISTINCT
修饰符指定是否应返回重复行。ALL
(默认值)指定应返回所有匹配的行,包括重复行。DISTINCT
指定从结果集中删除重复行。同时指定这两个修饰符是错误的。DISTINCTROW
是DISTINCT
的同义词。DISTINCT
可以与也使用WITH ROLLUP
的查询一起使用。HIGH_PRIORITY
使SELECT
的优先级高于更新表的语句。这只应将其用于非常快且必须立即完成的查询。如果在表被锁定以进行读取时发出SELECT HIGH_PRIORITY
查询,即使有更新语句在等待表释放,该查询也会运行。这仅影响仅使用表级锁定的存储引擎(例如MyISAM
、MEMORY
和MERGE
)。STRAIGHT_JOIN
强制优化器按照FROM
子句中列出的顺序联接表。如果优化器以非最佳顺序联接表,可以使用此选项来加快查询速度。STRAIGHT_JOIN
也可以在table_references
列表中使用。请参阅 第 15.2.13.2 节,“JOIN 子句”。STRAIGHT_JOIN
不适用于优化器将其视为const
或system
表的任何表。这样的表生成一行,在查询执行的优化阶段读取,并且在查询执行继续之前,对其列的引用将替换为相应的列值。这些表在EXPLAIN
显示的查询计划中排在第一位。请参阅 第 10.8.1 节,“使用 EXPLAIN 优化查询”。此例外情况可能不适用于在外联接的 NULL 补充侧(即LEFT JOIN
的右侧表或RIGHT JOIN
的左侧表)上使用的const
或system
表。SQL_BIG_RESULT
或SQL_SMALL_RESULT
可以与GROUP BY
或DISTINCT
一起使用,以分别告诉优化器结果集有很多行或很小。对于SQL_BIG_RESULT
,如果创建了基于磁盘的临时表,MySQL 会直接使用它们,并且更倾向于排序而不是使用带有GROUP BY
元素键的临时表。对于SQL_SMALL_RESULT
,MySQL 使用内存中的临时表来存储结果表,而不是使用排序。通常不需要这样做。SQL_BUFFER_RESULT
强制将结果放入临时表中。这有助于 MySQL 尽早释放表锁,并在将结果集发送到客户端需要很长时间的情况下有所帮助。此修饰符只能用于顶级SELECT
语句,不能用于子查询或UNION
之后的语句。SQL_CALC_FOUND_ROWS
告诉 MySQL 计算结果集中将有多少行,而忽略任何LIMIT
子句。然后可以使用SELECT FOUND_ROWS()
检索行数。请参阅 第 14.15 节,“信息函数”。注意SQL_CALC_FOUND_ROWS
查询修饰符和随附的FOUND_ROWS()
函数已弃用;预计在未来版本的 MySQL 中将删除它们。有关替代策略的信息,请参阅FOUND_ROWS()
的说明。SQL_CACHE
和SQL_NO_CACHE
修饰符在 MySQL 9.0 之前与查询缓存一起使用。查询缓存已在 MySQL 9.0 中删除。SQL_CACHE
修饰符也被删除。SQL_NO_CACHE
已弃用,并且没有效果;预计在未来的 MySQL 版本中将删除它。