MySQL select语法(一):一般查询
MySQL 查询语法 会涉及:一般查询语句,JOIN联接查询,UNION联合查询,括号查询表达式
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] ...
}
table_references:
escaped_table_reference [, escaped_table_reference] ...
escaped_table_reference: {
table_reference
| { OJ table_reference }
}
table_reference: {
table_factor
| joined_table
}
table_factor: {
tbl_name [PARTITION (partition_names)]
[[AS] alias] [index_hint_list]
| [LATERAL] table_subquery [AS] alias [(col_list)]
| ( table_references )
}
joined_table: {
table_reference {[INNER | CROSS] JOIN | STRAIGHT_JOIN} table_factor [join_specification]
| table_reference {LEFT|RIGHT} [OUTER] JOIN table_reference join_specification
| table_reference NATURAL [INNER | {LEFT|RIGHT} [OUTER]] JOIN table_factor
}
join_specification: {
ON search_condition
| USING (join_column_list)
}
join_column_list:
column_name [, column_name] ...
index_hint_list:
index_hint [, index_hint] ...
index_hint: {
USE {INDEX|KEY}
[FOR {JOIN|ORDER BY|GROUP BY}] ([index_list])
| {IGNORE|FORCE} {INDEX|KEY}
[FOR {JOIN|ORDER BY|GROUP BY}] (index_list)
}
index_list:
index_name [, index_name] ...
- 1、select_expr 表示希望获取的列,至少要有一个 select_expr
- 2、table_references 表示从哪些表中获取数据行
- 3、可以使用 PARTITION 从句指定分区列表,所查到的数据都是这些分区中的数据
- 4、WHERE 从句给出过滤条件,确定要查询的行。如果没有条件where,则查询所有行。where_condition 是一个表达式,可以使用MySQL支持的除聚合函数外的所有 函数 和 操作符。
- 5、select 语句可以不引用任何表
mysql> SELECT 1 + 1;
-> 2
# 为了方便使用FROM 从句获取其他从句而不实际引用表,查询语句允许使用虚拟表名 DUAL 来替代表名
mysql> SELECT 1 + 1 FROM DUAL;
-> 2
- 6、各个从句是有一定顺序的,如:HAVING 语句 必须在 GROUP BY 后面,ORDER BY 在 HAVING 后面。INTO 语句可以出现在多个位置,但只能出现一次。
- 7、select_expr 可以是指定的列名,表达式,以及 *
- 1)select_expr 仅仅包含 * 表示查询所有表的所有列
- 2)tbl_name.* 表示 查询该表的所有列
- 3)如果表包含 隐藏的列 * 和 tbl_name.* 并不包含这些列,需要明确指出列名
- 4)如果在有其他项的时候,使用 * ,会发生解析错误,为避免这个问题,需用 tbl_name.*
# t1 t2 的全部列
SELECT * FROM t1 INNER JOIN t2 ...
#明确指出 t1 t2 的全部列
SELECT t1.*, t2.* FROM t1 INNER JOIN t2 ...
# 有聚合函数,不能单纯使用 *
SELECT AVG(score), t1.* FROM t1 ...
- 6、select_expr 可以使用别名 : AS alias_name,这别名可以用在 GROUP BY, ORDER BY, or HAVING 中,且关键字 AS 是可选的。在 WHERE 从句中不要使用 列的别名,因为条件执行时,别名的值可能还没有确定下来。
SELECT CONCAT(last_name,', ',first_name) AS full_name
FROM mytable ORDER BY full_name;
SELECT CONCAT(last_name,', ',first_name) full_name
FROM mytable ORDER BY full_name;
# 注意 逗号,有逗号就是两列,没有逗号就是别名
SELECT columna, columnb FROM mytable;
- 7、FROM table_references 从句指定了数据表,如果不止一个表,那么是一个连接查询。每个表都可以指定别名。使用索引提示可以 为优化器提供在查询中如何选择索引的信息。
tbl_name [[AS] alias] [index_hint]
- 8、表名也可以使用 别名: 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;
- 9、在ORDER BY 和 GROUP BY 从句中可以使用 SELECT 查询的列名、列的别名、列的位置(从1开始的整数)。使用整数位置的方式已经过时了。
ORDER BY 默认是 ASC(升序排列)。排序会使用系统变量 max_sort_length 的值,该值表示最多比较多少个字节的字符。
# 先按 region 升序排,当region相同时,按 seed 降序排
SELECT college, region, seed FROM tournament
ORDER BY region ASC, seed DESC;
# 结果同上
SELECT college, region AS r, seed AS s FROM tournament
ORDER BY r, s DESC;
# 都是升序排
SELECT college, region, seed FROM tournament
ORDER BY 2, 3;
- 10、HAVING 从句 和 WHERE 类似 都是指定条件的,但WHERE 不能使用 聚合函数,HAVING可以。一般HAVING 都是跟在 GROUP BY 后面。
SELECT user, MAX(salary) FROM users
GROUP BY user HAVING MAX(salary) > 10;
- 11、WINDOW 从句,定义命名的窗口,用于 window functions。
- 12、在 ORDER BY 从句中,MySQL解析未修饰的 列,先是从 select_expr 中查找,然后在 FROM 从句后的表中查找。而 GROUP BY 或 HAVING 从句 是先从 FROM 从句的表中查找,然后再从 select_expr 中查找。
- 13、LIMIT 从句是用来 限制返回数据行的,有两个参数,都是非负整数。
- 1)在预处理语句中,可以使用问号 ? 作为占位符
- 2)在存储过程中,可以使用 整数的路由参数或本地变量。
- 3) 两个参数,第一个是返回行的第一行的偏移数(从0 开始),第二参数是 可以返回数据最大行数。如果只有一个参数,则表示偏移量为0
SELECT * FROM tbl LIMIT 5,10; # Retrieve rows 6-15
# 如果要返回 某个偏移量后的所有行,第二个参数可以是一个很大的数
SELECT * FROM tbl LIMIT 95,18446744073709551615;
SELECT * FROM tbl LIMIT 5; # Retrieve first 5 rows
# 预处理语句
SET @a=1;
PREPARE STMT FROM 'SELECT * FROM tbl LIMIT ?';
EXECUTE STMT USING @a;
- 14、 FOR UPDATE,FOR SHARE, NOWAIT
- 1)在使用页或行锁的存储引擎(如,InnoDB)中使用 FOR UPDATE,会在查询过程中,给所要查找的行加上锁,直到当前事务结束。
- 2)FOR SHARE 和 LOCK IN SHARE MODE 可以分享锁,允许其他事务读取被查询的行,但不能更新和删除。
- 3)FOR UPDATE 和 FOR SHARE 都支持 NOWAIT, SKIP LOCKED, 以及 OF tbl_name 选项。LOCK IN SHARE MODE 和 FOR SHARE 是一个意思,但不支持 NOWAIT, SKIP LOCKED, 以及 OF tbl_name 选项
- 4)NOWAIT 可以让 FOR UPDATE,FOR SHARE 查询立即执行,如果查询结果有被另一个事务上了锁的,会返回错误。
- 5)SKIP LOCKED可以让 FOR UPDATE,FOR SHARE 查询立即执行,如果查询结果有被另一个事务上了锁的,会排除这些上锁的结果行。
- 6)NOWAIT and SKIP LOCKED 选项对于基于语句的复制集是不安全的
- 7)OF tbl_name 选项是用来 为 FOR UPDATE and FOR SHARE 查询指定表名的。如果省略了 OF tbl_name 选项,那么在查询中所有被引用的表都会加上锁。给已经上锁的表,在上锁会报错。
- 8)如果语句中给表指定了别名,上锁语句只会给别名上锁;相反,如果没有指定表的别名,那么会给实际的表名上锁。
SELECT * FROM t1, t2 FOR SHARE OF t1 FOR UPDATE OF t2;
- 15、在 关键字 SELECT 之后,可以跟一些 修饰符
- 1)ALL 默认的修饰符,所有符合条件的行都会返回,包括重复的行
- 2)DISTINCT 移除重复出现的行(即只保留一个)。ALL 和 DISTINCT 只能出现其中一个。DISTINCTROW 和 DISTINCT 一样的作用
- 3)HIGH_PRIORITY 将 SELECT 语句的优先级设置得高于 UPDATE 语句。查询的优先级比更新的高,这会使得表锁住,而更新语句处于等待状态。该修饰符只在使用表级锁的存储引擎(如 MyISAM, MEMORY, and MERGE)起作用,且不能在 UNION 中使用。
- 4)STRAIGHT_JOIN 可以使MySQL优化器将 在 FROM 后面的 表按顺序 连接,可以加速查询。该修饰符也可用在 table_references 中。
- 5) SQL_BIG_RESULT 和 SQL_SMALL_RESULT 可以用在 GROUP BY 或 DISTINCT 语句中,告诉优化器查询结会 很大 或 很小。对于 SQL_BIG_RESULT ,如果有临时表的话,会使用基于硬盘的临时表用于排序。对于SQL_SMALL_RESULT会使用基于内存的临时表来存储结果,而不是排序。
- 6) SQL_BUFFER_RESULT 会强制将结果存储在临时表中,有利于MySQL更早地释放表的锁,也会在需要很长时间来发送结果给客户端的情况下有所帮助。该修饰符只能在顶级的 SELECT 语句中使用,而不能在子查询或 UNION 中使用。
- 7)SQL_CALC_FOUND_ROWS 会让 MySQL 计算结果集会有多少行,会无视 LIMIT 从句。行数可以通过 SELECT FOUND_ROWS() 函数来获取。
- 8) SQL_CACHE and SQL_NO_CACHE 是在 MySQL8.0 之前的版本中的,SQL_CACHE 已经移除,SQL_NO_CACHE 已废弃,且不起作用了。
https://dev.mysql.com/doc/refman/8.0/en/select.html
https://dev.mysql.com/doc/refman/8.0/en/index-hints.html
https://dev.mysql.com/doc/refman/8.0/en/server-system-variables.html#sysvar_max_sort_length
https://dev.mysql.com/doc/refman/8.0/en/group-by-modifiers.html
https://dev.mysql.com/doc/refman/8.0/en/window-functions-usage.html
https://dev.mysql.com/doc/refman/8.0/en/window-functions-named-windows.html
https://dev.mysql.com/doc/refman/8.0/en/join.html