• 首页
  • vue
  • TypeScript
  • JavaScript
  • scss
  • css3
  • html5
  • php
  • MySQL
  • redis
  • jQuery
  • 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语句和子查询。请参见“ 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 + 1 FROM DUAL;
    -> 2
    

    DUAL纯粹是为了方便那些要求所有SELECT语句都应该有FROM其他条款的人。MySQL可能会忽略这些子句。FROM DUAL如果没有引用表,MySQL不需要。

    通常,必须严格按照语法说明中显示的顺序给出所使用的子句。例如,HAVING子句必须在任何GROUP BY子句之后和任何ORDER BY子句之前。该INTO子句(如果存在)可以出现在语法描述所指示的任何位置,但是在给定语句内只能出现一次,不能出现在多个位置。有关更多信息INTO,请参见“ SELECT ... INTO语句”。

    select_expr术语列表包括选择列表,该选择列表指示要检索的列。术语指定列或表达式,或者可以使用*-shorthand:

    • 仅包含一个不合格的选择列表*可以用作从所有表中选择所有列的速记:

      SELECT * FROM t1 INNER JOIN t2 ...
      
    • tbl_name.*可用作合格的速记来从命名表中选择所有列:

      SELECT t1.*, t2.* FROM t1 INNER JOIN t2 ...
      
    • *在选择列表中将不合格项与其他项目一起使用可能会产生解析错误。为避免此问题,请使用合格的tbl_name.*参考

      SELECT AVG(score), t1.* FROM t1 ...
      

    以下列表提供了有关其他SELECT子句的其他信息:

    • select_expr可以使用给定的一个别名。别名用作表达式的列名,并且可以在被使用,或条款。例如:AS alias_nameGROUP BYORDER BYHAVING

      SELECT CONCAT(last_name,', ',first_name) AS full_name
        FROM mytable ORDER BY full_name;
      

      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.4.4.4节“列别名的问题”。

    • 该子句指示要从中检索行的一个或多个表。如果您命名多个表,则说明您正在执行联接。有关连接语法的信息,请参见“ JOIN子句”。对于指定的每个表,您可以选择指定别名。FROM table_references

      tbl_name [[AS] alias] [index_hint]
      

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

      您可以使用另一种方式来强制MySQL选择键扫描而不是表扫描。请参见“服务器系统变量”。SET max_seeks_for_key=value

    • 您可以将默认数据库中的表称为tbl_namedb_nametbl_name明确指定数据库。你可以参考一列col_nametbl_namecol_namedb_nametbl_namecol_name。您无需指定tbl_namedb_nametbl_name列引用的前缀,除非引用不明确。有关需要更明确的列引用形式的歧义示例,请参见“标识符限定符”。
    • 表引用可以使用或别名。这些语句是等效的: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发生在子查询中并且也应用于外部查询,则最外面ORDER BY的优先。例如,以下语句的结果按降序而不是升序排序:

      (SELECT ... ORDER BY a) ORDER BY a DESC;
      

      不建议使用列位置,因为该语法已从SQL标准中删除。

    • 在MySQL 8.0.13之前,MySQL支持非标准语法扩展,该扩展允许使用显式ASCDESC指定的GROUP BY列。MySQL 8.0.12和更高版本支持ORDER BY分组功能,因此不再需要使用此扩展。(错误#86312,错误#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 BYGROUP 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 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子句(如果存在)定义了可以由窗口函数引用的命名窗口。有关详细信息,请参见“命名为Windows”。
    • MySQL ORDER BY通过在select_expr值中搜索值,然后在FROM子句中的表的列中进行搜索,来解析子句中不合格的列或别名引用。对于GROUP BYor HAVING子句,它将FROM在搜索select_expr值之前搜索子句。(对于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_countLIMIT 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发生在子查询中并且也应用于外部查询,则最外面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_tablenew_table

      FOR SHARELOCK IN SHARE MODE设置共享锁,以允许其他事务读取已检查的行,但不允许更新或删除它们。FOR SHARELOCK IN SHARE MODE相等。然而FOR SHARE,喜欢FOR UPDATE,支持NOWAITSKIP LOCKED和选项。是的替代,但仍可用于向后兼容。OF tbl_nameFOR SHARELOCK IN SHARE MODELOCK IN SHARE MODE

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

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

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

      注意

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

      OF tbl_name应用FOR UPDATEFOR SHARE查询命名表。例如:

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

      当省略时,查询块引用的所有表均被锁定。因此,不结合其他锁定子句使用锁定子句将返回错误。在多个锁定子句中指定相同的表将返回错误。如果在语句中将别名指定为表名,则锁定子句只能使用别名。如果该语句未明确指定别名,则locking子句只能指定实际的表名。OF tbl_nameOF tbl_nameSELECTSELECT

      有关详细信息FOR UPDATE,并FOR SHARE请参见第15.7.2.4,“锁定读”。有关NOWAITSKIP LOCKED选项的更多信息,请参见使用NOWAIT和SKIP LOCKED锁定读取并发。

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

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

      在MySQL 8.0.12和更高版本中,DISTINCT可以与也使用的查询一起使用WITH ROLLUP。(缺陷#87450,错误#26640100)

    • HIGH_PRIORITYSELECT更新表的语句相比,其优先级更高。您只应将此用于非常快速且必须立即执行的查询。SELECT HIGH_PRIORITY即使有一条更新语句等待表空闲,在表被锁定以读取时发出的查询也会运行。这会影响只使用表级锁只存储引擎(例如MyISAMMEMORYMERGE)。

      HIGH_PRIORITY不能与SELECT组成部分的语句一起使用UNION

    • STRAIGHT_JOIN强制优化器按照表在FROM子句中列出的顺序连接表。如果优化器以非最佳顺序连接表,则可以使用它来加快查询速度。STRAIGHT_JOIN也可以在table_references列表中使用。请参见“ JOIN子句”。

      STRAIGHT_JOIN不适用于优化程序视为constsystem表的任何表。这样的表产生一行,在查询执行的优化阶段读取该表,并在执行查询之前用适当的列值替换对其列的引用。这些表将首先显示在由表示的查询计划中EXPLAIN。请参见“使用EXPLAIN优化查询”。此异常可能不适用于constsystem那些在使用的表NULL外的-complemented侧连接(即,a的右侧表LEFT JOIN或的左侧表RIGHT JOIN

    • SQL_BIG_RESULTSQL_SMALL_RESULT可以与GROUP BYDISTINCT一起使用,以告诉优化器结果集分别具有很多行或很小。对于SQL_BIG_RESULT,如果创建了基于磁盘的临时表,则MySQL直接使用基于磁盘的临时表,并且更喜欢排序而不是使用在GROUP BY元素上带有键的临时表。对于SQL_SMALL_RESULT,MySQL使用内存中的临时表来存储结果表,而不是使用排序。通常不需要。
    • SQL_BUFFER_RESULT强制将结果放入临时表中。这有助于MySQL及早释放表锁,并在将结果集发送到客户端花费很长时间的情况下提供帮助。此修饰符只能用于顶级SELECT语句,不能用于子查询或following UNION
    • SQL_CALC_FOUND_ROWS告诉MySQL计算结果集中将有多少行,而不管任何LIMIT子句。然后可以使用获取行数SELECT FOUND_ROWS()。请参见“信息函数”。

      注意

      从 MySQL 8.0.17开始不赞成使用SQL_CALC_FOUND_ROWS查询修饰符和附带FOUND_ROWS()函数,并且在将来的MySQL版本中将删除该修饰符和伴随函数。有关FOUND_ROWS()替代策略的信息,请参见说明。

    • SQL_CACHESQL_NO_CACHE改进剂与之前的MySQL 8.0查询缓存使用。查询缓存已在MySQL 8.0中删除。该SQL_CACHE修改被移除。SQL_NO_CACHE不推荐使用,不起作用,并且在将来的MySQL版本中将其删除。