Select查询语句作用是从现存的一个或多个表中查看满足条件的数据,selectel查询支持条件过滤、分组、排序、合并、嵌套查询等特性,完整的查询语法如下:
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_expr:要查询的字段,至少要有一个select_expr,如果要查询所有的字段可以使用”*”代替,Select_expr也可以使用MySQL内部的函数,另外字段也可以使用别名
Table_references:查询数据来自的一个或者多个表
Group by:代表分组,通常和聚合函数配合使用,如最大值max, 最小值min, 平均值avg, 个数count,求和sum
Order by:表示查询结果按照顺序排列,默认是升序排列,可以指定DESC表明按照降序排列
Having:一般是跟在group by子句之后,代表限制分组之后的结果
Limit:用来限制查询结果的显示的条数
INTO:代表将查询结果写入文件中或者定义的参数变量中
For update:将查询的数据行加上写锁,直到本事务提交为止
Lock in share mode:代表将查询的数据行加上读锁,则其他的链接可以读相同的数据但无法修改加锁的数据
ALL|Distinct:代表是否将查询结果中完全重复的行都查询出来,ALL是默认值代表都查询出来,distinct代表重复行只显示一次
HIGH_PRIORITY:代表赋予读操作较高的操作优先级
STRAIGHT_JOIN:强制优化器在表连接操作时按照语句中from子句中的表的顺序执行
SQL_SMALL_RESULT] [SQL_BIG_RESULT:通常是和group by/distinct一起使用,作用是事先告诉优化器查询结果是大还是小,以便优化器事先准备好将查询结果存放在磁盘临时表或者快速临时表中以便后续操作
SQL_BUFFER_RESULT:强制将查询结果存入临时表中
SQL_CALC_FOUND_ROWS:要求查询结果的同时计算结果的行数,以便后续通过SELECT FOUND_ROWS()直接获取行数
SQL_CACHE | SQL_NO_CACHE:是否直接从query cache中获取查询结果
(1)单表基本查询
# 查询student表中的所有数据
mysql> select * from student;
# 查询mysql的user表中的所有用户的用户名和主机
mysql> select user,host from mysql.user;
# 只查看查到的前两个用户的信息
mysql> select user,host from mysql.user limit 2;
# 查看student表中的所有数据只显示sid最大的两条数据
mysql> select * from student order by sid desc limit 2;
(2)单表关键字范围匹配查询
IN关键字:用来查询满足指定范围内的条件记录,也可使用not in查询不是指定范围的数据。
# 查询sid为5到8的数据
mysql> select * from student where sid in (5,8);
# 查询sid不在5和8之间的数据
mysql> select * from student where sid not in (5,8);
BETWEEN AND:用法和IN类似,用来查询某个范围内的值,也可使用”NOT BETWEEN AND”查询不再指定范围内的值。
# 查询sid为5到8的数据
mysql> select * from student where sid BETWEEN 5 AND 8;
# 查询sid不在5和8之间的数据
mysql> select * from student where sid NOT BETWEEN 5 AND 8;
LIKE:LIKE用于通过通配符进行匹配查询,like支持的通配符有”%”和”_”,”_”只能匹配一个字符。
# 查询student表中name字段以s开头的数据
mysql> select * from student where sname like "n%";
# 查询student表中sname字段以d开头且只有两个字符的数据
mysql> select sid,sname from student where sname like "d_";
IS NULL:查询字段为空的数据,也可使用”IS NOT NULL”查询字段为非空的值。
# 查询student表中gender字段为空的数据
mysql> select sname,gender from student where gender IS NULL;
# 查询student表中gender字段部位空的数据
mysql> select sname,gender from student where gender IS NOT NULL;
(3)带AND或OR的多条件查询
AND:AND用于连接多个查询条件,AND操作符限定只有所有的条件满足时才会返回结果。
OR:OR也用于连接多个查询条件,OR操作符限定满足其中一个条件是即可返回查询结果。
# 查询student表中sid为5(包含5)到8(不包含8)之间的数据
mysql> select sid,sname from student where sid >= 5 and sid < 8;
# 查询sid不再5到8之间的数据
mysql> select sid,sname from student where sid < 5 or sid > 8;
(4)查询结果中不显示重复数据
# 查询student表的gender字段的值并不显示重复行(默认值为all,是显示的)
mysql> select distinct gender from student;
(5)查询结果排序
ORDER BY:order by用于对查询的结果进行排序,也可以根据多个不同的字段对查询结果进行排序;默认排序正序,如果要使用倒序排序需要在排序的字段后面加”desc’.
# 依据name字段对查询的结果进行排序
mysql> select sid,sname from student order by sname;
# 对查询出的字段依据sname字段倒序排序
mysql> select sid,sname from student order by sname desc;
# 查询student中数据先依据sname倒序排序,在依据sid倒序排序
mysql> select sid,sname from student order by sname desc,sid desc;
(6)分组查询
分组查询是对数据按照某个或多个字段进行分组,使用”GROUP BY 分组字段”对数据进行分组,使用”HAVING”指定满足限定表达式条件。
Group by关键字通常和聚合函数一起使用,如MAX()、MIN()、COUNT()、SUM()、AVG()、GROUP_COUCAT()。
# 依据sname字段对student表中的数据进行分组
mysql> select sname,COUNT(*) AS total from student GROUP BY sname;
+-----------+-------+
| sname | total |
+-----------+-------+
| dayi | 2 |
| name_test | 2 |
……
+-----------+-------+
# 根据sname对student表分组查询,并将每个sname的sid显示出来
mysql> select sname,GROUP_CONCAT(sid) AS NAMES from student GROUP BY sname;
+-----------+-------+
| sname | NAMES |
+-----------+-------+
| dayi | 4,14 |
| dayi123 | 5,15 |
……
+-----------+-------+
分组查询中也可以使用条件限制,与普通查询不同的时分组查询的限制条件使用”HAVING”做条件限定。
# 根据sname对student表分组查询,并将sname中sid数量为1 的数据显示出来
mysql> select sname,GROUP_CONCAT(sid) AS NAMES from student GROUP BY sname HAVING COUNT(sid) = 1;
+-------+-------+
| sname | NAMES |
+-------+-------+
| aaa | 21 |
+-------+-------+
WITH ROLLUP:分组查询中的”WITH ROLLUP”用于统计记录的数量,会在所有查询出的分组记录之后增加一条记录,该记录计算查询出所有记录的总和。
# 会在查询结果中插入一行,统计记录数量
mysql> select sname,COUNT(*) AS total from student GROUP BY sname WITH ROLLUP;
+-----------+-------+
| sname | total |
+-----------+-------+
| aaa | 1 |
……
| NULL | 11 |
+-----------+-------+
7 rows in set (0.00 sec)
使用”GROUP BY”分组时,可以对多个字段分组,在”GROUP BU”后面跟需要分组的字段即可对多个字段分组;多字段分组是根据多字段的值来进行层次分组,分组层次从左到右,先按第一个地段分组,然后在第一个字段值相同的记录中,再根据第二个字段的值进行分组。
# 先根据sname分组,再根据sid分组,并对分组的结果依据sid反向排序
mysql> select * from student group by sname,sid order by sid desc;
在查询时,当两个或多个表中存在相同意义的字段时,可以通过这些字段对不同的表进行连接查询;连接查询时关系型数据库中的主要查询,主要包括内连接和外连接。
(1)内连接查询
内连接(INNER JOIN)是使用比较运算符进行表间某列数据的比较操作,并列出这些表中与连接条件向匹配的数据行。
# 通过dept_id关联查询出teacher表中的name,id以及student表中的name,id
mysql> select sid,sname,id,name from student,teacher where student.dept_id=teacher.dept_id;
+-----+-------+-----+-------+
| sid | sname | id | name |
+-----+-------+-----+-------+
| 2 | liyi | 102 | carey |
+-----+-------+-----+-------+
1 rows in set (0.38 sec)
# 通过inner join 来关联两个表查询,查询结果一样
mysql> select sid,sname,id,name from student inner join teacher on student.dept_id=teacher.dept_id;
(2)外连接查询
LEFT JOIN(左连接):返回包括在左表中的所有记录和右表中连接字段相等的记录
RIGHT JOIN(右连接):返回包括右表中的所有记录和左表中连接字段相等的记录
外连接查询将查询多个表中相关联的行,相对于内连接外连接查询出的数据还包含没有关联的行中数据;外连接分为左外连接和左连接,右外连接和右连接。
# 左连接查询,会列出左表中的所有数据,并列出右表中的所有数据
mysql> select sname,name from student left outer join teacher on student.dept_id=teacher.dept_id;
+-----------+-------+
| sname | name |
+-----------+-------+
| liyi | carey |
| name_test | NULL |
| dayi | NULL |
| dayi123 | NULL |
+-----------+-------+
4 rows in set (2.33 sec)
# 列出右表(teacher)表中的所有数据,并列出左表中相匹配的数据
mysql> select sname,name from student right outer join teacher on student.dept_id=teacher.dept_id;
+-------+-------+
| sname | name |
+-------+-------+
| liyi | carey |
+-------+-------+
1 rows in set (0.00 sec)
在查询时可以使用”UNION”或”UNION ALL”关键字将多条SELECT语句的查询结果合并成单个结果集。在合并时,两个表对应的烈数和数据类型必须相同。
”UNION”和”UNION ALL”的区别在于对查询结果UNION去重,UNION ALL不去重
# 查询teacher和teacher_backup中的所有数据并合并,使用union all合并不去重
mysql> select * from teacher UNION ALL select * from teacher_backup;
+-----+-------+---------+
| id | name | dept_id |
+-----+-------+---------+
| 102 | carey | 2 |
| 2 | ruth | 2 |
| 102 | carey | 2 |
+-----+-------+---------+
3 rows in set (0.00 sec)
# 使用union合并去重
mysql> select * from teacher UNION select * from teacher_backup;
+-----+-------+---------+
| id | name | dept_id |
+-----+-------+---------+
| 102 | carey | 2 |
| 2 | ruth | 2 |
+-----+-------+---------+
2 rows in set (0.00 sec)
如果相对union语句的最后结果做排序或者limit限制,则需要将每个select语句用括号括起来,把order by或limit语句放在最后。
# 对查询结果进行排序并显只示两条数据
mysql> (select * from teacher) UNION ALL (select * from teacher_backup) order by id limit 2;
+-----+-------+---------+
| id | name | dept_id |
+-----+-------+---------+
| 2 | ruth | 2 |
| 102 | carey | 2 |
+-----+-------+---------+
2 rows in set (0.00 sec)
(1)为表去别名查询
在查询时如果表名很长或者执行一些特殊查询时,为了方便操作或者多次使用相同的表时,可以使用表的别名来带起表名。使用表名的方法为”表名 AS 表别名”
# 使用teacher表别名查询数据
mysql> select tb.id from teacher AS tb where tb.id=102;
+-----+
| id |
+-----+
| 102 |
+-----+
1 row in set (0.00 sec)
(2)为字段取别名
为字段取别名原理同为表去别名原理相似。
# 为字段取别名查询
mysql> select st.sname AS student_name,st.sid AS student_id from student AS st where st.sid<=3;
+--------------+------------+
| student_name | student_id |
+--------------+------------+
| liyi | 2 |
| name_test | 3 |
+--------------+------------+
2 rows in set (0.00 sec)
Mysql查询结果默认是输出到标准的输出设备,mysql查询结果也可以输出到指定的文件中或变量中。Mysql将查询结果存入定义的变量或者文件是通过”select …into”语句完成的。
Select…INTO vat_list:将查询结果存入定义的变量。
Select…INTO OUTFILE:将查询结果按一定的格式写入到文件中
Select…INTO DUMPFILE:将查询结果以一行的格式写入到文件中,且只能写入一行
(1)将查询结果写入变量
需要保证查询结果返回一行,如果不返回数据则报no data错误,如果返回多行则报Result consisted of more than one row错误,当返回行数不确定时,可以用limit 1强制只返回一行。
# 将查询结果写入变量中,查询结果只能有一行
mysql> select sname,sid into @x,@y from student where sid=1;
Query OK, 0 rows affected, 1 warning (0.00 sec)
# 查看保存的变量
mysql> select @x,@y;
+------+------+
| @x | @y |
+------+------+
| NULL | NULL |
+------+------+
1 row in set (0.00 sec)
(2)将查询结果保存到文件中
要将查询结果保存到文件中时,在mysql配置中需要添加” secure_file_priv=/PATH/”,并要重启mysql使配置生效;文件会创建在本地服务器上,所以要确保用户能创建文件,而且该路径下不能存在同名的文件,以免被覆盖。
# 将查询结果保存到”/tmp/ slect_student.txt”,并制定分隔符为”,”,换行符为回车
mysql> select sname,sid into outfile '/tmp/slect_student.txt' fields terminated by ',' optionally enclosed by "" lines terminated by '\n' from course.student;
Query OK, 11 rows affected (0.18 sec)
# 使用dumpfile时只能保存查询出的一行数据
mysql> select sid,sname into dumpfile '/tmp/select_student2.txt' from course.student limit 1;
Query OK, 1 row affected (0.01 sec)
子查询是指一个查询语句嵌套在另一个查询语句内部的查询。子查询中常用的操作符有ANY(SOME)、ALL、IN、EXISTS,子查询也可以添加到SELECT、UPDATE和DELETE语句中,并且可以多层嵌套,子查询中也可使用比较运算符。
(1)带ANY、SOME关键字的子查询
ANY和SOME作用相同,表示满足其中任一条件,它们允许创建一个表达式对子查询的返回值列表进行比较,只要满足内存查询的任何一个比较条件,就返回一个结果作为外层子查询的条件。
# 只有student中的sid大于student02中的任一一个sid就返回查询的数据
mysql> select sid,sname from student where sid > any (select sid from student02);
+-----+-----------+
| sid | sname |
+-----+-----------+
| 13 | name_test |
| 14 | dayi |
| 15 | dayi123 |
| 20 | dy |
| 100 | test_name |
| 101 | ly |
+-----+-----------+
(2)带ALL关键字的子查询
使用ALL时需要同时满足所有内层查询的条件
# 使用all时student中的sid大于student02中的所有的sid时才返回数据
mysql> select sid,sname from student where sid > all (select sid from student02);
+-----+-----------+
| sid | sname |
+-----+-----------+
| 100 | test_name |
| 101 | ly |
+-----+-----------+
(3)带EXISTS关键字的子查询
EXISTS关键字后面的参数是一个任意的子查询,系统对子查询进行运算以判断它是否返回行,如果至少返回一行,nameEXISTS的结果为True,此时外层的查询语句将进行查询。如果子查询没有返回任何行,则EXISTS的返回结果为false,外层语句将不进行查询。NOT EXISTS作用与EXISTS作用相反
# 由于存在student02中存在sid=20的数据,所以会返回查询结果
mysql> select sid,sname from student where sid >= 20 and exists (select sid from student02 where sid=15);
+-----+-----------+
| sid | sname |
+-----+-----------+
| 20 | dy |
| 100 | test_name |
| 101 | ly |
+-----+-----------+
(4)带in关键字的子查询
使用IN关键字进行子查询时,内存查询语句仅需返回一列数据,返回的数据将提供给外层查询语句进行比较操作。NOT IN作用与IN相反。
# in关键字查询相当于求交集
mysql> select sid,sname from student where sid in (select sid from student02);
+-----+-----------+
| sid | sname |
+-----+-----------+
| 12 | liyi |
| 13 | name_test |
| 14 | dayi |
| 15 | dayi123 |
| 20 | dy |
+-----+-----------+
(5)带比较运算符的子查询
在子查询时可以使用比较运算符如”<”,”<=”,”=”,”>”,”>=”和”!=”等。
# 查看报了’carey’老师的课程的学生。
mysql> select sid,sname from student where dept_id=(select dept_id from teacher where name='carey');
+-----+-------+
| sid | sname |
+-----+-------+
| 2 | liyi |
| 12 | liyi |
+-----+-------+
视图是一种虚拟表,建立在基本表的基础上,通过关联一个表或者多个表来获取多个表中需要的字段,视图只是用来查询数据并不能用来存储数据信息。
(1)创建视图的语句
CREATE
[OR REPLACE]
[ALGORIHM = {UNDEFINED | MERGE | TEMPTABLE}]
[DEFINER = { user | CURRENT_USER }]
[SQL SECURITY { DEFINER | INVOKER }]
VIEW view_name [(column_list)]
AS select_statement
[WITH [CASCADED | LOCAL] CHECK OPTION]
各选项说明:
Or replace:关键词表示当创建的视图已经存在时,执行替换命令
Select_statement:子句则是创建视图的select语句,可以是从表中查询数据,也可以从其他视图中查询数据
(1)创建视图
# 创建视图,视图中的主要信息为student表中的sid小于10的sname,sid
mysql> create view student_view as select sid,sname from student where sid < 10;
Query OK, 0 rows affected (0.00 sec)
# 查询视图中的信息
mysql> select * from student_view where sid=2;
+-----+-------+
| sid | sname |
+-----+-------+
| 2 | liyi |
+-----+-------+
1 row in set (0.00 sec)
# 使用or replace覆盖创建的视图
mysql> create or replace view student_view as select sid,sname from student where sid >= 20;
(2)创建视图的其他选项
当视图被创建之后,则其定义就已经固定不会再改变,后续对源表增加的字段不会成为视图的一部分,而后续对表删除字段则会导致查询视图失败。
Order by子句在创建视图过程中是允许的,但当后续的查询视图的语句中有自己的order by子句时则会被忽略掉。
视图在满足特定条件时是可以执行insert/update/delete语句的,条件就是视图中的每一行和视图对应的表中的每行数据都能一一对应起来。
# 在创建的视图中插数入据,原表中也会插入数据
mysql> insert into student_view values(100,'test_name');
Query OK, 1 row affected (0.01 sec)
# 更新视图中数据,同时视图所对应的原表中的数据也会更改
mysql> update student_view set sname='abcd' where sid=21;
Query OK, 1 row affected (0.01 sec)
Rows matched: 1 Changed: 1 Warnings: 0
# 通过视通删除数据,同时视图对应的原表中的数据也会被删除
mysql> delete from student_view where sid=21;
Query OK, 1 row affected (0.00 sec)
(3)修改视图
视图被创建后,也可通过”alter view”语句来修改视图的定义,作用和”create or replace view”语句相同。
# 修改视图
mysql> alter view student_view as select sid,sname from student where sid = 2;
Query OK, 0 rows affected (0.00 sec)
(4)删除视图
删除视图时通过”drop view语句来删除”。
# 删除创建的视图
mysql> drop view student_view;
Query OK, 0 rows affected (0.00 sec)
# 加了”if exists”再次删除时不会报错
mysql> drop view if exists student_view;
Query OK, 0 rows affected, 1 warning (0.00 sec)