zoukankan      html  css  js  c++  java
  • 13.2.9 SELECT 语法

    以下内容均翻译自 MySQL 5.6 Reference Manual 来自一个四级都还没过的渣渣 通过阅读官方文档加深对一些sql注入的理解

    13.2.9.1 SELECT ... INTO Syntax
    13.2.9.2 JOIN Syntax
    13.2.9.3 UNION Syntax

    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 ...]
        [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 OUTFILE 'file_name'
            [CHARACTER SET charset_name]
            export_options
          | INTO DUMPFILE 'file_name'
          | INTO var_name [, var_name]]
        [FOR UPDATE | LOCK IN SHARE MODE]]
    

    SELECT用于从一个或多个表中取回行,可以包含UNION语句和子查询。参见第13.2.9.3节,UNION语法,和第13.2.10节,Subquery语法。

    SELECT语句最常用的子句是:

    • 每个select_expr指示要检索的列。 必须至少有一个select_expr。

    • table_references指示要从中检索行的一个或多个表。 其语法在第13.2.9.2节“JOIN语法”中描 述。

    • SELECT支持使用partition关键字进行显式分区选择,在table_reference中的表名后面有一个分区或子分区列表(或两者都有)(请参见第13.2.9.2节“联接语法”)。在这种情况下,只从列出的分区中选择行,而忽略表中的任何其他分区。有关更多信息和示例,请参见第19.5节“分区选择”。

    • SELECT ... PARTITION from tables using storage engines such as MyISAM that perform table-level locks (and thus partition locks) lock only the partitions or subpartitions named by the PARTITION option.

      For more information, see Section 19.6.4, “Partitioning and Locking”.

    • WHERE子句(如果给定)指示要选择行必须满足的一个或多个条件。where_condition是一个表达式,对于要选择的每一行,其计算结果为true。如果没有WHERE子句,该语句将选择所有行。

      在WHERE表达式中,您可以使用MySQL支持的任何函数和运算符,聚合(摘要)函数除外。参见第9.5节“表达式”和第12章“函数和运算符”。

    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子句可以如语法描述中所示出现,也可以紧跟在select_expr列表之后出现。 有关INTO的更多信息,请参见第13.2.9.1节“SELECT ... INTO语法”。

    select_expr列表术语包含选择列表,该列表指示要检索哪些列。术语指定列或表达式,或者可以使用 * 来简写

    • 一个只包含一个非限定 * 的选择列表可以用作从所有表中选择所有列的简写
      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子句的附加信息:

    • 可以使用 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.4.4.4节,列别名的问题。

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

      tbl_name [[AS] alias] [index_hint]
      

      index_hint的使用为优化器提供了关于如何在查询处理过程中选择索引的信息。有关指定这些提示的语法描述,请参见第8.9.3节“索引提示”。

      您可以使用SET max seek for key=value作为另一种强制MySQL选择键扫描而不是表扫描的方法。参见第5.1.7节,服务器系统变量。

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

    • 引用表时可以使用 tbl_name AS alias_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出现在子查询中并且也应用于外部查询,则最外面的ORDER BY优先。例如,以下语句的结果按降序排列,而不是升序排列:

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

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

    • MySQL扩展了GROUP BY子句,因此您还可以在子句中指定的列之后指定ASCDESC

      SELECT a, COUNT(b) FROM test_table GROUP BY a DESC;
      
    • 如果使用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或DESC指示符的情况下进行排序)。要生成给定的排序顺序,请为“GROUP BY”列使用显式的ASC或DESC指示符,或者提供ORDER BY子句。

    • 当您使用ORDER BY或GROUP BY对SELECT中的列进行排序时,服务器仅使用max_sort_length系统变量指示的初始字节数对值进行排序。

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

    • GROUP BY允许WITH ROLLUP修饰符。 请参见第12.19.2节“GROUP BY Modifiers”。

    • 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列中的列名。

    • 不要对应该出现在WHERE子句中的项使用HAVING。例如,不要写下面的内容

      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使用不同的名称。

    • MySQL通过搜索select_expr值,然后在FROM子句中的表的列中搜索ORDER BY子句中的非限定列或别名引用。 对于GROUP BY或HAVING子句,它在搜索select_expr值之前搜索FROM子句。 (对于GROUP BY和have,这与mysql 5.0之前的行为不同,后者使用与ORDER BY相同的规则。)

    • LIMIT子句可用于约束SELECT语句返回的行数。LIMIT接受一个或两个数值参数,除了这些例外,它们都必须是非负整数常量

      • 在prepared statements中,LIMIT参数可以使用?占位符标记。
      • 在stored programs中,LIMIT参数可以使用integer-valued routine parameters或局部变量来指定。
        使用两个参数,第一个参数指定要返回的第一行的偏移量,第二个参数指定要返回的最大行数。第一行的偏移量是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。

      对于prepared statements,可以使用占位符。下面的语句将从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;
      
    • PROCEDURE子句指定应处理结果集中数据的过程。 有关示例,请参见第8.4.2.4节“使用PROCEDURE ANALYZE”,其中介绍了ANALYZE,该过程可用于获取可能有助于减小表大小的最佳列数据类型的建议。

      UNION语句中不允许使用PROCEDURE子句。

    • SELECT的SELECT ... INTO形式使查询结果能够写入文件或存储在变量中。 有关更多信息,请参见第13.2.9.1节“SELECT ... INTO语法”。

    • 如果对使用页锁或行锁的存储引擎使用FOR UPDATE,则查询检查的行将被写入锁定,直到当前事务结束。 使用LOCK IN SHARE MODE设置共享锁,允许其他事务读取已检查的行,但不允许更新或删除它们。 请参见第14.7.2.4节“锁定读取”。

      此外,您不能在诸如CREATE TABLE new_table SELECT ... FROM old_table ....之类的语句中使用FOR UPDATE作为SELECT的一部分。(如果您尝试这样做,语句将被拒绝,并显示错误 Can't update table 'old_table' while 'new_table' is being created.)这是MySQL 5.5及更早版本的行为更改,它允许CREATE TABLE ... SELECT语句在正在创建的表之外的表中进行更改。

    在SELECT关键字之后,您可以使用许多影响语句操作的修饰符。 HIGH_PRIORITY(高优先级),STRAIGHT_JOIN(直连接)和以SQL_开头的修饰符是标准SQL的MySQL扩展。

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

    • 高优先级赋予SELECT比更新表的语句更高的优先级。您应该只将它用于非常快速且必须立即完成的查询。即使有更新语句等待表释放,在表被锁定读取时发出的SELECT HIGH_PRIORITY查询也会运行。这仅影响仅使用表级锁定的存储引擎(如MyISAM、MEMORY和MERGE)。

      HIGH_PRIORITY不能与属于UNION的SELECT语句一起使用。

    • STRAIGHT _ JOIN强制优化器按照表在FROM子句中列出的顺序来连接表。如果优化器以非最佳顺序连接表,您可以使用它来加速查询。还可以在table_references列表中使用STRAIGHT _ JOIN。参见第13.2.9.2节“连接语法”。

      STRAIGHT_JOIN不适用于优化程序视为const或system的任何表。 这样的表生成单行,在查询执行的优化阶段读取,并且在查询执行进行之前用适当的列值替换对其列的引用。 这些表将首先出现在EXPLAIN显示的查询计划中。 请参见第8.8.1节“使用EXPLAIN优化查询”。 此异常可能不适用于在外连接的NULL补充端(即LEFT JOIN的右侧表或RIGHT JOIN的左侧表)上使用的const或系统表。

    • SQL_BIG_REQUESTSQL_SMAll_REQUEST可以与GROUP BY或DISTINCT一起使用,分别告诉优化器结果集有许多行或很小。对于SQL_BIG_REQUEST,如果创建了基于磁盘的临时表,MySQL会直接使用它们,并且更喜欢使用临时表中在GROUP BY元素里的键进行排序。 对于SQL_SMALL_RESULT,MySQL使用内存中的临时表来存储生成的表而不是使用排序。 通常不需要这样做。

    • SQL_BUFFER_RESULT强制将结果放入临时表中。 这有助于MySQL尽早释放表锁,并在需要很长时间将结果集发送到客户端的情况下提供帮助。 此修饰符只能用于顶级SELECT语句,不能用于子查询或UNION之后。

    • SQL_CALC_FOUND_ROWS告诉MySQL计算结果集中将有多少行,忽略任何LIMIT子句。 然后可以使用SELECT FOUND_ROWS()检索行数。 请参见第12.15节“信息功能”。

    • SQL_CACHESQL_NO_CACHE修饰符会影响查询缓存中查询结果的缓存(请参见第8.10.3节“MySQL查询缓存”)。 SQL_CACHE告诉MySQL将结果存储在查询缓存中(如果它是可缓存的,并且query_cache_type系统变量的值是2或DEMAND)。 使用SQL_NO_CACHE,服务器不使用查询缓存。 它既不检查查询缓存,也不检查结果是否已缓存,也不缓存查询结果。 (由于解析器中的限制,空格字符必须位于SQL_NO_CACHE关键字之前和之后;非空格(如换行符)会导致服务器检查查询缓存以查看结果是否已缓存。)

      这两个修饰符是互斥的,如果同时指定它们则会发生错误。 此外,子查询(包括FROM子句中的子查询)和第一个SELECT以外的联合中的SELECT语句不允许使用这些修饰符。

      对于视图,如果SQL_NO_CACHE出现在查询中的任何SELECT中,则适用。 对于可高速缓存的查询,如果SQL_CACHE出现在查询引用的视图的第一个SELECT中,则应用SQL_CACHE。

    使用存储引擎从分区表中进行选择,例如使用表级锁的MyISAM,只锁定那些包含与SELECT语句WHERE子句匹配的行的分区。(使用行级锁定的存储引擎(如InnoDB)不会出现这种情况。)有关更多信息,请参见第19.6.4节“分区和锁定”。

  • 相关阅读:
    ZOJ 2158 Truck History
    Knight Moves (zoj 1091 poj2243)BFS
    poj 1270 Following Orders
    poj 2935 Basic Wall Maze (BFS)
    Holedox Moving (zoj 1361 poj 1324)bfs
    ZOJ 1083 Frame Stacking
    zoj 2193 Window Pains
    hdu1412{A} + {B}
    hdu2031进制转换
    openjudge最长单词
  • 原文地址:https://www.cnblogs.com/BxScope/p/10859260.html
Copyright © 2011-2022 走看看