MySQLSELECT语法(⼀)SELECT语法详解
源⾃MySQL 5.7 官⽅⼿册:
SELECT的语法如下:
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解析
SELECT⽤于从⼀个或者多个表中取回数据⾏,也可以包括UNION语句和⼦查询。UNION语句参考后续⽂章,⽽⼦查询在⼿册13.2.10节。
SELECT语句最常⽤的⼦句有这些:
每个select_expr指⽰要检索的列。所以必须⾄少有⼀个select_expr。
table_references指⽰要从中取回⾏数据的⼀个或多个表。其语法在第13.2.9.2节“JOIN语法”中描述。
SELECT⽀持使⽤PARTITION显式分区选择,其中包含table_reference中表的名称后⾯的分区或⼦分区(或两者)列表。关于分区的更多信息在Section 22.6.4, “Partitioning and Locking”
如果存在WHERE⼦句,其中的条件对⾏数据进⾏筛选。where_condition是⼀个表达式,对于要选择的每⼀⾏,其计算结果为true。如果没有WHERE⼦句,该语句将选择所有⾏。在WHERE表达式中,您可以使⽤除聚合函数之外的任何MySQL⽀持的函数和运算符。See Section 9.5, “Expressions”, and Chapter 12, Functions and Operators.
SELECT也可⽤于检索计算的⾏⽽不引⽤任何表。
mysql>SELECT1+1;
->2
在没有引⽤表的情况下,允许将DUAL指定为虚拟表名:
mysql>SELECT1+1FROM DUAL;
->2
DUAL的存在只是为了⽅便。MySQL可能会忽略这些⼦句。如果没有引⽤表,MySQL不需要FROM DUAL。
通常,使⽤的⼦句必须完全按照语法描述中展⽰的顺序给出。
例如,HAVING⼦句必须位于任何GROUP BY⼦句之后和任何ORDER BY⼦句之前。例外情况是INTO⼦句可以如语法描述中所⽰出现,也可以紧跟在select_expr列表之后出现。INTO后续⽂章会讲。
select_expr项列表包括了要取回的列,该项可以指定⼀个字段、⼀个表达式或者使⽤*号。
SELECT列表中只包含⼀个*号,即⾮限定*,意味着从所有表中取回所有的列。
⽽tb.*,限定*,表⽰取回⼀个指定表中的所有列。
在SELECT列表中使⽤⾮限定的*,可能会产⽣解析错误。要注意使⽤场合,
⼆、关于SELECT⼦句的⼀些附加知识:
2.1
可以使⽤AS alias_name为select_expr指定别名。别名⽤作表达式的列名,可⽤于GROUP BY,ORDER BY或HAVING⼦句。
AS关键字是可选项,在指定列的别名时养成使⽤AS是⼀种好习惯。
MySQL不允许在WHERE⼦句中引⽤列的别名,因为当WHERE⼦句执⾏时,列值可能还尚未确定。See Section B.4.4.4, “Problems with Column Aliases”.
2.2
FROM后的table_references指⽰参与查询的⼀个或者多个表。如果列出了多个表,就会执⾏JOIN操作。⽽对于每⼀个指定表,都可以为其定义别名。
tbl_name [[AS] alias] [index_hint]
使⽤index_hint,会为优化器提供有关如何在查询处理期间选择索引的信息。关于它,see Section 8.9.4, “Index Hints”。
当然,也可以使⽤SET max_seeks_for_key = value作为替代⽅法,强制MySQL更优先使⽤键扫描⽽不是表扫描。See Section 5.1.7, “Server System Variables”
2.3
不使⽤AS也能为表定义别名,直接空格后填写即可。
mysql面试题详解 2.4
SELECT后被选择的列,可以在ORDER IN和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 BY2, 3;
如果ORDER BY出现在⼦查询中,并且也应⽤于外部查询,则最外层的ORDER BY优先。
例如,以下语句的结果按降序排序,⽽不是按升序排序:
(SELECT ... ORDER BY a) ORDER BY a DESC;
不推荐使⽤代表列位置的数字的⽅法,因为这已经从标准SQL中删除。
2.5
如果使⽤了GROUP BY,被分组的列会⾃动按升序排列(就好像有⼀个ORDER BY语句后⾯跟了同样的列)。如果要避免GROUP BY因为⾃动排序⽣成的开销,添加ORDER BY NULL可以解决:
SELECT a, COUNT(b) FROM test_table GROUP BY a ORDER BY NULL;
虽然在GROUP BY语句上也有⼀些对字段指定排序的⽤法,但是他们现在都已经被抛弃。正确的做法是,使⽤ORDER BY⼦句来进⾏排序。
2.6
当使⽤ORDER BY或GROUP BY对SELECT中的列进⾏排序时,服务器仅使⽤max_sort_length系统变量指⽰的初始字节数对值进⾏排序。aspen换热器中英文对照
2.7
MySQL扩展了GROUP BY的⽤法,它允许在Select列表中出现没有在GROUP BY中进⾏分组的字段。这点在前⾯的聚合函数的⽂章中已经讲得很清楚。
2.8
GROUP BY⼦句允许添加WITH ROLLUP修饰符
2.9
gcc和vs编译器的差异 Having⼦句⼀般应⽤在最后,恰好在结果集被返回给MySQL客户端前,且没有进⾏优化。(⽽LIMIT应⽤在HAVING后)
SQL标准要求:HAVING必须引⽤在GROUP BY列表中或者聚合函数使⽤的列。然⽽,MySQL对此进⾏了扩展,它允许HAVING引⽤Select⼦句列表中的列,还有外部⼦查询的列。
如果HAVING引⽤的列具有歧义,会有警告产⽣。下⾯的语句中,col2具有歧义:
SELECT COUNT(col1) AS col2 FROM t GROUP BY col2 HAVING col2 =2;
这⾥没报错只有警告是为什么呢?因为MySQLS虽然对标准SQL进⾏了扩展,但是在这种情况下,标准SQL的选择具有优先权。即MySQL把HAVING中的col2优先指向GROUP BY中的col2。
2.11
切记不要在该使⽤WHERE的地⽅使⽤HAVING。HAVING是和GROUP BY搭配的。
2.12
HAVING⼦句可以引⽤聚合函数,⽽WHERE不能。
SELECT user, MAX(salary) FROM users
GROUP BY user HAVING MAX(salary) >10;
上⾯的查询在⽼版本的MySQL可能⽆效。
2.13
MySQL允许重复的列名。也就是说,同名的select_expr可以有多个。这是对标准SQL的扩展。⽽因为MySQL允许GROUP BY和HAVING引⽤select_expr 值,这可能会引起歧义:
SELECT12AS a, a FROM t GROUP BY a;
switchcase表达方法 在这个语句中,两个列都名为a(实际应该是不同)。(着应该是被允许的)
那么为了不引起歧义以对正确的列进⾏分组,切记对select_expr使⽤不同的别名。
2.14
对于ORDER BY⼦句中的⾮限定列或别名引⽤,MySQL是这样进⾏解析的:先搜索SELECT⼦句列表中的select_expr值,然后在FROM后的表中的列。
⽽对于GROUP BY和HAVING⼦句中的⾮限定列或别名,MySQL先搜索FROM⼦句,再搜索SELECT⼦句。
2.15
LIMIT⼦句可⽤于约束SELECT语句返回的⾏数。
LIMIT可以有⼀个或者两个参数,都必须为⾮负整数。
但是也有例外情况:
在预编译的语句中,LIMIT参数可以使⽤占位符标记——“?” 进⾏指定。
在存储的程序(存储过程?)中,可以使⽤整数值例程参数(integer-valued routine parameters)或局部变量指定LIMIT参数。
若LIMIT有两个参数,第⼀个指定相对于第⼀⾏的偏移量,第⼆个参数指定应该返回的⾏数。第⼀⾏⾃⼰的偏移量是0,⽽不是1:
/*取回结果集中的6~15⾏*/
SELECT*FROM tbl LIMIT 5,10;
那如果要取回⼀个设定某个偏移量之后的所有⾏,可以为第⼆参数设定⼀个⾮常⼤的常量。以下查询取回从第96⾏起的所有数据:
SELECT*FROM tbl LIMIT 95,18446744073709551615;
若LIMIT只有⼀个参数,则参数指定应该取回的⾏数,偏移量默认为0,即从第⼀⾏起。
对于预编译SQL语句,可以使⽤占位符:
/*取回第⼀⾏数据*/
SET@a=1;
PREPARE STMT FROM'SELECT * FROM tbl LIMIT ?';
EXECUTE STMT USING @a;
/*取回第2~6⾏数据*/
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,此时最外层查询的LIMIT优先。例如,以下语句返回的⾏应该是2条,⽽不是1条:
(SELECT ... LIMIT 1) LIMIT 2;
2.16
PROCEDURE⼦句命名了⼀个对结果集进⾏处理的存储过程。Section 8.4.2.4, “Using PROCEDURE ANALYSE” 这⼀节,描述了ANALYSE关键字的使⽤。⼀个存储过程,可⽤于获取有助于减少表⼤⼩的最佳列数据类型的建议。(点进去才发现从MySQL 5.7.18开始,PROCEDURE ANALYZE()已被弃⽤,并在MySQL 8.0中被删除。)
2.17
INTO可以让查询结果写⼊到⽂件或者保存到变量中,后续的⽂章会讲这个。
2.18
如果使⽤在⼀个使⽤了页级锁或者⾏级锁的存储引擎中使⽤FOR UPDATE,被某个查询所检查的⾏将会处于“写锁定”中,直到当前事务结束。使⽤LOCK IN SHARE MODE设置共享锁,允许其他事务读取已检查的⾏,但不允许更新或删除它们。See Section 14.7.2.4, “Locking Reads”.
此外,你不能在下⾯的语句中将FOR UPDATE作为SELECT查询的⼀部分:
CREATE TABLE new_table SELECT ... FROM old_table ....
如果尝试这么做,该语句会被拒绝,并报错——Can't update table 'old_table' while 'new_table' is being created。在MySQL 5.5以及更早的版本中有所不同。(This is a change in behavior from MySQL 5.5 and earlier, which permitted CREATE TABLE ... SELECT statements to make changes in tables other than the table being created.)
三、SELECT关键字的修饰符
紧跟SELECT关键字,你可以使⽤⼀些列修饰符,来影响语句的操作。
HIGH_PRIORITY,STRAIGHT_JOIN和以SQL_开头的修饰符是标准SQL的MySQL扩展。
3.1
ALL和DISTINCT修饰符指定是否对结果集中的⾏(应该不是某个列)去重。
ALL是默认修饰符,即满⾜要求的所有⾏都要被取回来。
DISTINCT删除重复的⾏。
oa办公系统源码下载 3.2
HIGH_PRIORITY修饰符会让SELECT语句⽐更改表(这⾥英⽂⽤得是update,不晓得是更新还是更改)的语句有更⾼的优先级。
这个修饰符只应该在⾮常快且能被⽴即执⾏的查询当中使⽤。
在表被锁定以进⾏读取时发出的SELECT HIGH_PRIORITY查询也会运⾏,即使有⼀个更新语句正在等待表被释放。这仅影响仅使⽤表级锁定的存储引擎(例如MyISAM,MEMORY和MERGE)。
strcmp函数输入字母顺序
HIGH_PRIORITY不能与属于UNION的SELECT语句⼀起使⽤。
3.3
STRAIGHT_JOIN强制优化器按照FROM⼦句中列出的顺序连接表。如果优化程序以⾮最佳顺序连接表,则可以使⽤此⽅法加速查询.STRAIGHT_JOIN也可以在table_references列表中使⽤。JOIN语法中会讲到。
STRAIGHT_JOIN不适⽤于被优化器视为const或system的任何表。这种表只产⽣⼀⾏数据,在查询执⾏的优化阶段读取,并且在查询执⾏进⾏之前⽤适当的列值替换对其列的引⽤。这些表将⾸先出现在EXPLAIN显⽰的查询计划中。See Section 8.8.1, “Optimizing Queries with EXPLAIN”.
This exception may not apply to const or system tables that are used on the NULL-complemented side of an outer join (that is, the right-side table of a LEFT JOIN or the left-side table of a RIGHT JOIN.
3.4
SQL_BIG_RESULT或SQL_SMALL_RESULT可以与GROUP BY或DISTINCT⼀起使⽤,分别告诉优化器结果集有很多⾏或者很⼩。
对于SQL_BIG_RESULT,MySQL直接使⽤基于磁盘的临时表(如果已创建),并且更偏向使⽤在GROUP BY中元素的key的临时表来进⾏排序。
对于SQL_SMALL_RESULT,MySQL使⽤内存中的临时表来存储⽣成的表⽽不是使⽤排序。通常不需要这样做。
3.5
SQL_BUFFER_RESULT强制将结果放⼊临时表中.
这有助于MySQL尽早释放表锁,在需要很长时间将结果集发送到客户端的情况下,这样也更好。
此修饰符只能⽤于顶级SELECT语句,不能⽤于⼦查询或UNION之后。
3.6
SQL_CALC_FOUND_ROWS告诉MySQL计算结果集中将有多少⾏,忽略任何LIMIT⼦句。
然后可以使⽤SELECT FOUND_ROWS()检索⾏数。See Section 12.15, “Information Functions”.
这个参数就是为了⽅便统计在不使⽤LIMIT时的结果集。
3.7
SQL_CACHE和SQL_NO_CACHE修饰符会影响查询缓存中查询结果的缓存。(see Section 8.10.3, “The MySQL Query Cache”)
SQL_CACHE告诉MySQL将结果存储在查询缓存中(如果它是可缓存的,并且query_cache_type系统变量的值是2或DEMAND)。
使⽤SQL_NO_CACHE,服务器不使⽤查询缓存。它既不检查查询缓存,也不检查结果是否已缓存,也不缓存查询结果。
这两个修饰符是互斥的,如果同时指定它们则会发⽣错误。
此外,⼦查询(包括FROM⼦句中的⼦查询)和第⼀个SELECT以外的UNION中的SELECT语句不允许使⽤这些修饰符。
对于视图,如果SQL_NO_CACHE出现在查询中的任何SELECT中,则适⽤
For a cacheable query, SQL_CACHE applies if it appears in the first SELECT of a view referred to by the query.
从MySQL 5.7.20开始,不推荐使⽤查询缓存,并在MySQL 8.0中删除。弃⽤包括SQL_CACHE和SQL_NO_CACHE。
最后还有⼀个关于对分表查询时锁定情况因存储引擎不同⽽不同的段落。
With SQL_NO_CACHE, the server does not use the query cache. It neither checks the query cache to see whether the result is already cached, nor does it cache the query result.
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论