文档首页
MySQL 9.0 参考手册
相关文档 下载本手册
PDF (US Ltr) - 40.0Mb
PDF (A4) - 40.1Mb
手册页 (TGZ) - 258.2Kb
手册页 (Zip) - 365.3Kb
信息 (Gzip) - 4.0Mb
信息 (Zip) - 4.0Mb


MySQL 9.0 参考手册  /  ...  /  SELECT 语句

15.2.13 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_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 操作和子查询。还支持 INTERSECTEXCEPT 操作。UNIONINTERSECTEXCEPT 运算符将在本节后面详细介绍。另见 第 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_nameselect_expr 指定别名。该别名用作表达式的列名,并且可以在 GROUP BYORDER BYHAVING 子句中使用。例如:

    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 table_references 子句指示要从中检索行的表。如果指定了多个表,则表示您正在执行联接。有关联接语法的更多信息,请参阅第 15.2.13.2 节,“JOIN 子句”。对于指定的每个表,您都可以选择指定一个别名。

    tbl_name [[AS] alias] [index_hint]

    索引提示的使用为优化器提供了有关如何在查询处理期间选择索引的信息。有关指定这些提示的语法说明,请参阅第 10.9.4 节,“索引提示”

    您可以使用 SET max_seeks_for_key=value 作为强制 MySQL 首选键扫描而不是表扫描的另一种方法。请参阅第 7.1.8 节,“服务器系统变量”

  • 您可以将默认数据库中的表称为 tbl_name,也可以称为 db_name.tbl_name 以显式指定数据库。您可以将列称为 col_nametbl_name.col_namedb_name.tbl_name.col_name。除非引用不明确,否则不需要为列引用指定 tbl_namedb_name.tbl_name 前缀。有关需要更明确的列引用形式的歧义示例,请参阅第 11.2.2 节,“标识符限定符”

  • 可以使用 tbl_name AS alias_nametbl_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 BYGROUP 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 BYGROUP BYSELECT 中的列进行排序时,服务器仅使用 max_sort_length 系统变量指示的初始字节数对值进行排序。

  • MySQL 扩展了 GROUP BY 的使用,以允许选择 GROUP BY 子句中未提及的字段。如果您没有从查询中获得预期的结果,请阅读第 14.19 节,“聚合函数”中对 GROUP BY 的说明。

  • HAVING 子句与 WHERE 子句类似,用于指定选择条件。WHERE 子句指定选择列表中列的条件,但不能引用聚合函数。HAVING 子句指定组的条件,通常由 GROUP BY 子句形成。查询结果仅包含满足 HAVING 条件的组。(如果没有 GROUP BY,则所有行都隐式地形成一个聚合组。)

    HAVING 子句几乎是最后应用的,就在将项发送到客户端之前,并且没有优化。(LIMITHAVING 之后应用。)

    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 BYHAVING 引用 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 BYHAVING 子句,它会在搜索 select_expr 值之前先搜索 FROM 子句。(对于 GROUP BYHAVING,这与 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 OFFSET offset 语法。

    如果 LIMIT 出现在带括号的查询表达式中,并且也应用于外部查询,则结果未定义,并且在未来版本的 MySQL 中可能会更改。

  • SELECT ... INTO 形式的 SELECT 使查询结果可以写入文件或存储在变量中。有关更多信息,请参阅 第 15.2.13.1 节,“SELECT ... INTO 语句”

  • 如果将 FOR UPDATE 与使用页面锁或行锁的存储引擎一起使用,则查询检查的行将被写锁定,直到当前事务结束。

    不能在诸如 CREATE TABLE new_table SELECT ... FROM old_table ... 的语句中将 FOR UPDATE 用作 SELECT 的一部分。(如果尝试这样做,该语句将被拒绝,并显示错误 创建“new_table”时无法更新表“old_table。)

    FOR SHARELOCK IN SHARE MODE 设置共享锁,允许其他事务读取检查的行,但不能更新或删除它们。FOR SHARELOCK IN SHARE MODE 是等效的。但是,与 FOR UPDATE 一样,FOR SHARE 也支持 NOWAITSKIP LOCKEDOF tbl_name 选项。FOR SHARELOCK IN SHARE MODE 的替代品,但为了向后兼容,LOCK IN SHARE MODE 仍然可用。

    NOWAIT 会导致 FOR UPDATEFOR SHARE 查询立即执行,如果由于另一个事务持有的锁而无法获取行锁,则返回错误。

    SKIP LOCKED 会导致 FOR UPDATEFOR SHARE 查询立即执行,从结果集中排除被另一个事务锁定的行。

    NOWAITSKIP LOCKED 选项对于基于语句的复制来说是不安全的。

    注意

    跳过锁定行的查询返回的数据视图不一致。因此,SKIP LOCKED 不适合一般的交易工作。但是,当多个会话访问同一个类似队列的表时,可以使用它来避免锁争用。

    OF tbl_nameFOR UPDATEFOR SHARE 查询应用于命名的表。例如

    SELECT * FROM t1, t2 FOR SHARE OF t1 FOR UPDATE OF t2;

    当省略 OF tbl_name 时,查询块引用的所有表都将被锁定。因此,将不带 OF tbl_name 的锁定子句与另一个锁定子句一起使用将返回错误。在多个锁定子句中指定同一个表将返回错误。如果在 SELECT 语句中将别名指定为表名,则锁定子句只能使用该别名。如果 SELECT 语句没有显式指定别名,则锁定子句只能指定实际的表名。

    有关 FOR UPDATEFOR SHARE 的更多信息,请参阅 第 17.7.2.4 节,“锁定读取”。有关 NOWAITSKIP LOCKED 选项的更多信息,请参阅 使用 NOWAIT 和 SKIP LOCKED 锁定读取并发

SELECT 关键字之后,可以使用许多修饰符来影响语句的操作。HIGH_PRIORITYSTRAIGHT_JOIN 以及以 SQL_ 开头的修饰符是 MySQL 对标准 SQL 的扩展。

  • ALLDISTINCT 修饰符指定是否应返回重复行。ALL(默认值)指定应返回所有匹配的行,包括重复行。DISTINCT 指定从结果集中删除重复行。同时指定这两个修饰符是错误的。DISTINCTROWDISTINCT 的同义词。

    DISTINCT 可以与也使用 WITH ROLLUP 的查询一起使用。

  • HIGH_PRIORITY 使 SELECT 的优先级高于更新表的语句。这只应将其用于非常快且必须立即完成的查询。如果在表被锁定以进行读取时发出 SELECT HIGH_PRIORITY 查询,即使有更新语句在等待表释放,该查询也会运行。这仅影响仅使用表级锁定的存储引擎(例如 MyISAMMEMORYMERGE)。

    HIGH_PRIORITY 不能与作为 UNION 的一部分的 SELECT 语句一起使用。

  • STRAIGHT_JOIN 强制优化器按照 FROM 子句中列出的顺序联接表。如果优化器以非最佳顺序联接表,可以使用此选项来加快查询速度。STRAIGHT_JOIN 也可以在 table_references 列表中使用。请参阅 第 15.2.13.2 节,“JOIN 子句”

    STRAIGHT_JOIN 不适用于优化器将其视为 constsystem 表的任何表。这样的表生成一行,在查询执行的优化阶段读取,并且在查询执行继续之前,对其列的引用将替换为相应的列值。这些表在 EXPLAIN 显示的查询计划中排在第一位。请参阅 第 10.8.1 节,“使用 EXPLAIN 优化查询”。此例外情况可能不适用于在外联接的 NULL 补充侧(即 LEFT JOIN 的右侧表或 RIGHT JOIN 的左侧表)上使用的 constsystem 表。

  • SQL_BIG_RESULTSQL_SMALL_RESULT 可以与 GROUP BYDISTINCT 一起使用,以分别告诉优化器结果集有很多行或很小。对于 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_CACHESQL_NO_CACHE 修饰符在 MySQL 9.0 之前与查询缓存一起使用。查询缓存已在 MySQL 9.0 中删除。SQL_CACHE 修饰符也被删除。SQL_NO_CACHE 已弃用,并且没有效果;预计在未来的 MySQL 版本中将删除它。