SELECT
[ALL | DISTINCT | DISTINCTROW ]
[HIGH_PRIORITY]
[STRAIGHT_JOIN]
[SQL_SMALL_RESULT] [SQL_BIG_RESULT] [SQL_BUFFER_RESULT]
[SQL_CACHE | 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}
[ASC | DESC], ... [WITH ROLLUP]]
[HAVING where_condition]
[ORDER BY {col_name | expr | position}
[ASC | DESC], ...]
[LIMIT {[offset,] row_count | row_count OFFSET offset}]
[PROCEDURE procedure_name(argument_list)]
[into_option]
[FOR UPDATE | LOCK IN SHARE MODE]
into_option: {
INTO OUTFILE 'file_name'
[CHARACTER SET charset_name]
export_options
| INTO DUMPFILE 'file_name'
| INTO var_name [, var_name] ...
}
SELECT
用于检索从一个或多个表中选择的行,并且可以包括
UNION
语句和子查询。请参阅第 13.2.9.3 节,“UNION 子句”和第 13.2.10节,“子查询”。
最常用的
SELECT
语句子句是:
每个都
select_expr
表示您要检索的列。必须至少有一个select_expr
。table_references
指示要从中检索行的一个或多个表。它的语法在第 13.2.9.2 节,“JOIN 子句”中描述。SELECT
PARTITION
支持使用带有分区列表或子分区(或两者) 的子句的显式分区选择,这些子句跟在 a 中的表名之后table_reference
(请参阅 第 13.2.9.2 节,“JOIN 子句”)。在这种情况下,仅从列出的分区中选择行,而忽略表的任何其他分区。有关更多信息和示例,请参阅 第 22.5 节,“分区选择”。SELECT ... PARTITION
来自使用存储引擎的表,例如MyISAM
执行表级锁(因此分区锁)仅锁定由PARTITION
选项命名的分区或子分区。有关详细信息,请参阅 第 22.6.4 节,“分区和锁定”。
该
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.9.1 节,“SELECT ... INTO 语句”。
术语列表select_expr
包含指示要检索哪些列的选择列表。术语指定列或表达式,或者可以使用
*
-shorthand:
只包含一个非限定的选择列表
*
可以用作从所有表中选择所有列的速记:SELECT * FROM t1 INNER JOIN t2 ...
可以用作限定速记来从命名表中选择所有列:tbl_name
.*SELECT t1.*, t2.* FROM t1 INNER JOIN t2 ...
对选择列表中的其他项目使用不合格
*
可能会产生分析错误。例如: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.9.2 节,“JOIN 子句”。对于每个指定的表,您可以选择指定一个别名。
FROM
table_references
tbl_name [[AS] alias] [index_hint]
索引提示的使用为优化器提供了有关如何在查询处理期间选择索引的信息。有关指定这些提示的语法的描述,请参阅 第 8.9.4 节,“索引提示”。
您可以使用 另一种方法来强制 MySQL 更喜欢键扫描而不是表扫描。请参阅 第 5.1.7 节,“服务器系统变量”。
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 扩展了该
GROUP BY
子句,因此您还可以在子句中命名的列之后指定ASC
和 。DESC
但是,此语法已弃用。要生成给定的排序顺序,请提供一个ORDER BY
子句。如果您使用
GROUP BY
,输出行将根据列进行排序,就GROUP BY
好像您ORDER BY
对相同的列有一个 。为避免GROUP BY
产生的排序开销,请添加ORDER BY NULL
:SELECT a, COUNT(b) FROM test_table GROUP BY a ORDER BY NULL;
依赖于隐式
GROUP BY
排序(即,在没有ASC
orDESC
指示符的情况下进行排序)或显式排序GROUP BY
(即,通过对列使用显式ASC
或DESC
指示符GROUP BY
)已被弃用。要生成给定的排序顺序,请提供一个ORDER 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 修饰符”。该
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
。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 版本中发生变化。一个
PROCEDURE
子句命名一个应该处理结果集中数据的过程。例如,请参阅 第 8.4.2.4 节,“使用过程分析”,其中描述ANALYSE
了一个过程,该过程可用于获取可能有助于减小表大小的最佳列数据类型的建议。PROCEDURE
语句中不允许 有子句UNION
。笔记PROCEDURE
从 MySQL 5.7.18 开始不推荐使用语法,并在 MySQL 8.0 中删除。的
SELECT ... INTO
形式SELECT
使查询结果可以写入文件或存储在变量中。有关详细信息,请参阅 第 13.2.9.1 节,“SELECT ... INTO 语句”。如果
FOR UPDATE
与使用页锁或行锁的存储引擎一起使用,则查询检查的行将被写锁定,直到当前事务结束。UsingLOCK IN SHARE MODE
设置一个共享锁,允许其他事务读取检查的行但不能更新或删除它们。请参阅 第 14.7.2.4 节,“锁定读取”。此外,您不能在语句中使用
FOR UPDATE
as 的一部分,SELECT
例如 . (如果您尝试这样做,该语句将被拒绝并显示错误 Can't update table ' ' while ' ' is being created。)这是 MySQL 5.5 及更早版本的行为更改,它允许 语句在表中进行更改除了正在创建的表。CREATE TABLE
new_table
SELECT ... FROMold_table
...old_table
new_table
CREATE TABLE ... SELECT
在SELECT
关键字之后,您可以使用一些影响语句操作的修饰符。HIGH_PRIORITY
、
STRAIGHT_JOIN
和以开头的修饰符
SQL_
是 MySQL 对标准 SQL 的扩展。
和 修饰符指定是否应返回重复行
ALL
。(默认值)指定应返回所有匹配行,包括重复项。 指定从结果集中删除重复行。同时指定两个修饰符是错误的。是的同义词 。DISTINCT
ALL
DISTINCT
DISTINCTROW
DISTINCT
HIGH_PRIORITY
SELECT
比更新表的语句具有更高的 优先级。您应该仅将此用于非常快且必须立即完成的查询。SELECT HIGH_PRIORITY
即使有更新语句等待表释放,在表被锁定以供读取时发出的 查询也会运行。这只会影响仅使用表级锁定的存储引擎(例如MyISAM
、MEMORY
和MERGE
)。STRAIGHT_JOIN
强制优化器按照它们在FROM
子句中列出的顺序连接表。如果优化器以非最佳顺序连接表,您可以使用它来加速查询。STRAIGHT_JOIN
也可以用在table_references
列表中。请参阅 第 13.2.9.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 节,“信息功能”。和修饰符影响查询缓存
SQL_CACHE
中SQL_NO_CACHE
查询结果的缓存(请参阅 第 8.10.3 节,“MySQL 查询缓存”)。如果结果可缓存并且系统变量的值为orSQL_CACHE
,则告诉 MySQL 将结果存储在查询缓存中 。对于,服务器不使用查询缓存。它既不检查查询缓存以查看结果是否已被缓存,也不缓存查询结果。query_cache_type
2
DEMAND
SQL_NO_CACHE
这两个修饰符是互斥的,如果同时指定它们就会出错。此外,这些修饰符不允许在子查询(包括
FROM
子句中的子查询)和SELECT
除第一个之外的联合语句中使用SELECT
。对于视图,
SQL_NO_CACHE
如果它出现在任何SELECT
查询中,则适用。对于可缓存的查询,SQL_CACHE
如果它出现在SELECT
查询引用的视图的第一个中,则应用。笔记查询缓存从 MySQL 5.7.20 开始弃用,并在 MySQL 8.0 中删除。弃用包括
SQL_CACHE
和SQL_NO_CACHE
。
来自使用表级锁SELECT
的存储引擎的分区表仅锁定那些包含与语句
子句匹配的行的分区。(这不会发生在存储引擎中,例如使用行级锁定的存储引擎。)有关更多信息,请参阅
第 22.6.4 节,“分区和锁定”。
MyISAM
SELECT
WHERE
InnoDB