SELECT语句
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_nameAS (window_spec) [, window_nameAS (window_spec)] ...] [ORDER BY {col_name | expr | position} [ASC |DESC ], ... [WITH ROLLUP ]] [LIMIT {[offset,] row_count | row_countOFFSET 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
语句和子查询。请参见“ UNION子句”和“子查询”。一个SELECT
语句可以用开始WITH
子句来定义内访问的公共表表达式SELECT
。请参见“ WITH(公用表表达式)”。
最常用的SELECT
语句子句如下:
- 每个
select_expr
表示您要检索的列。必须至少有一个select_expr
。 table_references
指示要从中检索行的一个或多个表。“ JOIN子句”中描述了其语法。SELECT
支持使用,PARTITION
在的表名之后使用分区或子分区(或两者)的列表进行显式分区选择table_reference
(请参见“ JOIN子句”)。在这种情况下,仅从列出的分区中选择行,并且忽略表的任何其他分区。有关更多信息和示例,请参见“分区选择”。WHERE
如果给出该子句,则表明必须满足行才能被选择的一个或多个条件。where_condition
是一个表达式,对于要选择的每一行,其值为true。如果没有WHERE
子句,该语句将选择所有行。在
WHERE
表达式中,可以使用MySQL支持的任何功能和运算符,但聚合(摘要)功能除外。请参见“表达式”和函数和运算符。
SELECT
也可以用于检索不参考任何表而计算的行。
例如:
mysql>SELECT 1 + 1; -> 2
DUAL
在未引用任何表的情况下,可以将其指定为虚拟表名称:
mysql>SELECT 1 + 1FROM DUAL ; -> 2
DUAL
纯粹是为了方便那些要求所有SELECT
语句都应该有FROM
其他条款的人。MySQL可能会忽略这些子句。FROM DUAL
如果没有引用表,MySQL不需要。
通常,必须严格按照语法说明中显示的顺序给出所使用的子句。例如,HAVING
子句必须在任何GROUP BY
子句之后和任何ORDER BY
子句之前。该INTO
子句(如果存在)可以出现在语法描述所指示的任何位置,但是在给定语句内只能出现一次,不能出现在多个位置。有关更多信息INTO
,请参见“ SELECT ... INTO语句”。
select_expr
术语列表包括选择列表,该选择列表指示要检索的列。术语指定列或表达式,或者可以使用*
-shorthand:
仅包含一个不合格的选择列表
*
可以用作从所有表中选择所有列的速记:SELECT *FROM t1INNER JOIN t2 ...tbl_name.*
可用作合格的速记来从命名表中选择所有列:SELECT t1.*, t2.*FROM t1INNER JOIN t2 ...*
在选择列表中将不合格项与其他项目一起使用可能会产生解析错误。为避免此问题,请使用合格的tbl_name.*
参考SELECT AVG(score), t1.*FROM t1 ...
以下列表提供了有关其他SELECT
子句的其他信息:
阿
select_expr
可以使用给定的一个别名。别名用作表达式的列名,并且可以在被使用,或条款。例如:AS alias_name
GROUP BY
ORDER BY
HAVING
SELECT CONCAT(last_name,', ',first_name)AS full_nameFROM mytableORDER BY full_name;AS
在给select_expr
标识符加上别名时,关键字是可选的。前面的示例可能是这样写的:SELECT CONCAT(last_name,', ',first_name) full_nameFROM mytableORDER BY full_name;但是,由于
AS
是可选的,因此如果忘记两个select_expr
表达式之间的逗号,则会出现一个细微的问题:MySQL将第二个表达式解释为别名。例如,在以下语句中,columnb
将其视为别名:SELECT columna columnbFROM mytable;因此,
AS
在指定列别名时,养成显式使用的习惯。不允许在
WHERE
子句中引用列别名,因为WHERE
执行子句时可能尚未确定列值。请参见第B.4.4.4节“列别名的问题”。该子句指示要从中检索行的一个或多个表。如果您命名多个表,则说明您正在执行联接。有关连接语法的信息,请参见“ JOIN子句”。对于指定的每个表,您可以选择指定别名。
FROM table_references
tbl_name [[
AS ] alias] [index_hint]索引提示的使用为优化器提供了有关在查询处理期间如何选择索引的信息。有关指定这些提示的语法的说明,请参见“索引提示”。
您可以使用另一种方式来强制MySQL选择键扫描而不是表扫描。请参见“服务器系统变量”。
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
列引用的前缀,除非引用不明确。有关需要更明确的列引用形式的歧义示例,请参见“标识符限定符”。 表引用可以使用或别名。这些语句是等效的:
tbl_name AS alias_name
tbl_name alias_name
SELECT t1.name , t2.salaryFROM employeeAS t1, infoAS t2WHERE t1.name = t2.name ;SELECT t1.name , t2.salaryFROM employee t1, info t2WHERE t1.name = t2.name ;可以在
ORDER BY
和GROUP BY
子句中使用列名,列别名或列位置引用选择用于输出的列。列位置是整数,从1开始:SELECT college, region, seedFROM tournamentORDER BY region, seed;SELECT college, regionAS r, seedAS sFROM tournamentORDER BY r, s;SELECT college, region, seedFROM tournamentORDER BY 2, 3;要以相反的顺序进行排序,请将
DESC
(降序)关键字添加到ORDER BY
排序依据的子句中的列名。默认为升序;可以使用ASC
关键字显式指定。如果
ORDER BY
发生在子查询中并且也应用于外部查询,则最外面ORDER BY
的优先。例如,以下语句的结果按降序而不是升序排序:(
SELECT ...ORDER BY a)ORDER BY aDESC ;不建议使用列位置,因为该语法已从SQL标准中删除。
在MySQL 8.0.13之前,MySQL支持非标准语法扩展,该扩展允许使用显式
ASC
或DESC
指定的GROUP BY
列。MySQL 8.0.12和更高版本支持ORDER BY
分组功能,因此不再需要使用此扩展。(错误#86312,错误#26073525)这也意味着您可以在使用时对任意列进行排序GROUP BY
,如下所示:SELECT a, b, COUNT(c)AS tFROM test_tableGROUP BY a,bORDER BY a,tDESC ;从MySQL 8.0.13开始,
GROUP BY
不再支持该扩展名:ASC
或不允许列DESC
指定符GROUP BY
。- 使用
ORDER BY
或GROUP BY
对中的列进行排序时SELECT
,服务器仅使用max_sort_length
系统变量指示的初始字节数对值进行排序。 - MySQL扩展了对的使用,
GROUP BY
以允许选择该GROUP BY
条款中未提及的字段。如果没有从查询中获得期望的结果,请阅读GROUP BY
在“聚合(组BY)函数”中找到的描述。 GROUP BY
允许WITH ROLLUP
修饰符。请参见“GROUP BY 修饰符”。以前,不允许
ORDER BY
在具有WITH ROLLUP
修饰符的查询中使用。自MySQL 8.0.12起,此限制已取消。请参见“GROUP BY 修饰符”。该
HAVING
子句几乎是最后一次应用,即将项目发送到客户端之前,没有进行优化。(LIMIT
在之后应用HAVING
。)SQL标准要求
HAVING
必须仅引用GROUP BY
子句中的列或聚合函数中使用的列。但是,MySQL支持对此行为的扩展,并允许HAVING
引用SELECT
列表中的列以及外部子查询中的列。如果该
HAVING
子句引用的列不明确,则会出现警告。在以下语句中,col2
是不明确的,因为它既用作别名又用作列名:SELECT COUNT(col1)AS col2FROM tGROUP BY col2HAVING col2 = 2;优先考虑标准SQL行为,因此,如果在输出列列表中
HAVING
使用列名GROUP BY
并将其用作别名列,则优先选择列中的GROUP BY
列。请勿
HAVING
用于该WHERE
条款中的项目。例如,不要写以下内容:SELECT col_nameFROM tbl_nameHAVING col_name > 0;改写这个:
SELECT col_nameFROM tbl_nameWHERE col_name > 0;该
HAVING
子句可以引用聚合函数,而该WHERE
子句不能:SELECT user , MAX(salary)FROM usersGROUP BY user HAVING MAX(salary) > 10;(这在某些旧版本的MySQL中不起作用。)
MySQL允许重复的列名。也就是说,可以有多个
select_expr
同名。这是对标准SQL的扩展。由于MySQL还允许GROUP BY
并HAVING
引用select_expr
值,因此可能导致歧义:SELECT 12AS a, aFROM tGROUP BY a;在该语句中,两个列都具有名称
a
。为确保将正确的列用于分组,请为每个使用不同的名称select_expr
。- 该
WINDOW
子句(如果存在)定义了可以由窗口函数引用的命名窗口。有关详细信息,请参见“命名为Windows”。 - MySQL
ORDER BY
通过在select_expr
值中搜索值,然后在FROM
子句中的表的列中进行搜索,来解析子句中不合格的列或别名引用。对于GROUP BY
orHAVING
子句,它将FROM
在搜索select_expr
值之前搜索子句。(对于GROUP BY
和HAVING
,这与使用与相同的规则的MySQL 5.0之前的行为不同ORDER BY
。) 该
LIMIT
子句可用于约束SELECT
语句返回的行数。LIMIT
接受一个或两个数字参数,这些参数必须都是非负整数常量,但以下情况除外:- 在准备好的语句中,
LIMIT
可以使用?
占位符标记指定参数。 - 在存储的程序中,
LIMIT
可以使用整数值的例程参数或局部变量来指定参数。
有两个参数,第一个参数指定要返回的第一行的偏移量,第二个参数指定要返回的最大行数。初始行的偏移量是0(不是1):
SELECT *FROM tblLIMIT 5,10; # Retrieve rows 6-15要检索从某个偏移量到结果集结尾的所有行,可以为第二个参数使用较大的数字。该语句检索从第96行到最后一行的所有行:
SELECT *FROM tblLIMIT 95,18446744073709551615;使用一个参数,该值指定从结果集的开头返回的行数:
SELECT *FROM tblLIMIT 5; # Retrieve first 5 rows换句话说,等于。
LIMIT row_count
LIMIT 0,row_count
对于准备好的语句,可以使用占位符。以下语句将从
tbl
表中返回一行:SET @a=1;PREPARE STMTFROM 'SELECT * FROM tbl LIMIT ?';EXECUTE STMTUSING @a;以下语句将返回表的第二到第六行
tbl
:SET @skip=1;SET @numrows=5;PREPARE STMTFROM 'SELECT * FROM tbl LIMIT ?, ?';EXECUTE STMTUSING @skip, @numrows;为了与PostgreSQL兼容,MySQL还支持语法。
LIMIT row_count OFFSET offset
如果
LIMIT
发生在子查询中并且也应用于外部查询,则最外面LIMIT
的优先。例如,以下语句产生两行,而不是一行:(
SELECT ...LIMIT 1)LIMIT 2;- 在准备好的语句中,
SELECT ... INTO
形式SELECT
使查询结果可以写入文件或存储在变量中。有关更多信息,请参见“ SELECT ... INTO语句”。如果
FOR UPDATE
与使用页锁或行锁的存储引擎一起使用,则查询检查的行将被写锁,直到当前事务结束为止。您不能将
FOR UPDATE
用作SELECT
语句的一部分,例如。(如果尝试这样做,该语句将被拒绝,并显示错误“创建'时无法更新表''。)CREATE TABLE new_table SELECT ... FROM old_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
或FOR SHARE
查询立即执行,如果由于另一个事务持有的锁而无法获得行锁,则返回错误。SKIP LOCKED
使FOR UPDATE
或FOR SHARE
查询立即执行,从结果集中排除被另一个事务锁定的行。NOWAIT
和SKIP LOCKED
选项对于基于语句的复制是不安全的。注意
跳过锁定行的查询将返回数据不一致的视图。
SKIP LOCKED
因此不适合一般交易工作。但是,当多个会话访问相同的类似队列的表时,可以使用它来避免锁争用。OF tbl_name
应用FOR UPDATE
并FOR SHARE
查询命名表。例如:SELECT *FROM t1, t2FOR SHARE OF t1FOR UPDATE OF t2;当省略时,查询块引用的所有表均被锁定。因此,不结合其他锁定子句使用锁定子句将返回错误。在多个锁定子句中指定相同的表将返回错误。如果在语句中将别名指定为表名,则锁定子句只能使用别名。如果该语句未明确指定别名,则locking子句只能指定实际的表名。
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_
是标准SQL的MySQL扩展。
在
ALL
和DISTINCT
修饰符指定重复行是否应该返回。ALL
(默认值)指定应返回所有匹配的行,包括重复行。DISTINCT
指定从结果集中删除重复的行。同时指定两个修饰符是错误的。DISTINCTROW
是的同义词DISTINCT
。在MySQL 8.0.12和更高版本中,
DISTINCT
可以与也使用的查询一起使用WITH ROLLUP
。(缺陷#87450,错误#26640100)HIGH_PRIORITY
与SELECT
更新表的语句相比,其优先级更高。您只应将此用于非常快速且必须立即执行的查询。SELECT HIGH_PRIORITY
即使有一条更新语句等待表空闲,在表被锁定以读取时发出的查询也会运行。这会影响只使用表级锁只存储引擎(例如MyISAM
,MEMORY
和MERGE
)。HIGH_PRIORITY
不能与SELECT
组成部分的语句一起使用UNION
。STRAIGHT_JOIN
强制优化器按照表在FROM
子句中列出的顺序连接表。如果优化器以非最佳顺序连接表,则可以使用它来加快查询速度。STRAIGHT_JOIN
也可以在table_references
列表中使用。请参见“ JOIN子句”。STRAIGHT_JOIN
不适用于优化程序视为const
或system
表的任何表。这样的表产生一行,在查询执行的优化阶段读取该表,并在执行查询之前用适当的列值替换对其列的引用。这些表将首先显示在由表示的查询计划中EXPLAIN
。请参见“使用EXPLAIN优化查询”。此异常可能不适用于const
或system
那些在使用的表NULL
外的-complemented侧连接(即,a的右侧表LEFT JOIN
或的左侧表RIGHT JOIN
。SQL_BIG_RESULT
或SQL_SMALL_RESULT
可以与GROUP BY
或DISTINCT
一起使用,以告诉优化器结果集分别具有很多行或很小。对于SQL_BIG_RESULT
,如果创建了基于磁盘的临时表,则MySQL直接使用基于磁盘的临时表,并且更喜欢排序而不是使用在GROUP BY
元素上带有键的临时表。对于SQL_SMALL_RESULT
,MySQL使用内存中的临时表来存储结果表,而不是使用排序。通常不需要。SQL_BUFFER_RESULT
强制将结果放入临时表中。这有助于MySQL及早释放表锁,并在将结果集发送到客户端花费很长时间的情况下提供帮助。此修饰符只能用于顶级SELECT
语句,不能用于子查询或followingUNION
。SQL_CALC_FOUND_ROWS
告诉MySQL计算结果集中将有多少行,而不管任何LIMIT
子句。然后可以使用获取行数SELECT FOUND_ROWS()
。请参见“信息函数”。注意
从 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版本中将其删除。