语法说明如下。 字段名:需要查询的字段名称。 <表1><表2>:需要内连接的表名。 INNER JOIN :内连接中可以省略 INNER 关键字,只用关键字 JOIN。 ON 子句:用来设置内连接的连接条件。 INNER JOIN 也可以使用 WHERE 子句指定连接条件,但是 INNER JOIN … ON 语法是官方的标准写法,而且 WHERE 子句在某些时候会影响查询的性能。 多个表内连接时,在 FROM 后连续使用 INNER JOIN 或 JOIN 即可。 内连接可以查询两个或两个以上的表。为了更好的理解,暂时只讲解两个表的连接查询。
例:在 students表和 tb_course 表之间,使用内连接查询学生姓名和相对应的课程名称
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
mysql> select s.name,c.course_name from students s inner join tb_course c on s.course_id = c.id; +--------+-------------+ | name | course_name | +--------+-------------+ | Dany | Java | | Green | MySQL | | Henry | Java | | jane | Python | | jim | MySQL | | john | Go | | Lily | Go | | Susan | C++ | | Thomas | C++ | | Tom | C++ | +--------+-------------+ 10 rows in set (0.00 sec)
左外连接又称为左连接,使用 LEFT OUTER JOIN 关键字连接两个表,并使用 ON 子句来设置连接条件。 左连接的语法格式如下: SELECT <字段名> FROM <表1> LEFT OUTER JOIN <表2> <ON子句>; 语法说明如下: 字段名:需要查询的字段名称。 <表1><表2>:需要左连接的表名。 LEFT OUTER JOIN:左连接中可以省略 OUTER 关键字,只使用关键字 LEFT JOIN。 ON 子句:用来设置左连接的连接条件,不能省略。 上述语法中,”表1”为基表,”表2”为参考表。左连接查询时,可以查询出”表1”中的所有记录和”表2”中匹配连接条件的记录。如果”表1”的某行在”表2”中没有匹配行,那么在返回结果中,”表2”的字段值均为空值(NULL)。
mysql> insert into students values(11,'shiqian',20,'man',188,6); Query OK, 1 row affected (0.00 sec)
mysql> select * from students; +----+---------+------+-------+--------+-----------+ | id | name | age | sex | height | course_id | +----+---------+------+-------+--------+-----------+ | 1 | Dany | 25 | man | 160 | 1 | | 2 | Green | 23 | man | 158 | 2 | | 3 | Henry | 23 | woman | 185 | 1 | | 4 | jane | 22 | man | 162 | 3 | | 5 | jim | 24 | woman | 175 | 2 | | 6 | john | 21 | woman | 172 | 4 | | 7 | Lily | 22 | man | 188 | 4 | | 8 | Susan | 22 | man | 179 | 5 | | 9 | Thomas | 22 | woman | 158 | 5 | | 10 | Tom | 23 | woman | 165 | 5 | | 11 | shiqian | 20 | man | 188 | 6 | +----+---------+------+-------+--------+-----------+ 11 rows in set (0.00 sec)
例:在 students 表和 tb_course 表中查询所有学生姓名和相对应的课程名称,包括没有课程的学生
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
mysql> select s.name,c.course_name from students s left outer join tb_course c on s.`course_id`=c.`id`; +---------+-------------+ | name | course_name | +---------+-------------+ | Dany | Java | | Henry | Java | | Green | MySQL | | jim | MySQL | | jane | Python | | john | Go | | Lily | Go | | Susan | C++ | | Thomas | C++ | | Tom | C++ | | shiqian | NULL | +---------+-------------+ 11 rows in set (0.00 sec)
右外连接又称为右连接,右连接是左连接的反向连接。使用 RIGHT OUTER JOIN 关键字连接两个表,并使用 ON 子句来设置连接条件。 右连接的语法格式如下: SELECT <字段名> FROM <表1> RIGHT OUTER JOIN <表2> <ON子句>; 语法说明如下: 字段名:需要查询的字段名称。 表1><表2>:需要右连接的表名。 RIGHT OUTER JOIN:右连接中可以省略 OUTER 关键字,只使用关键字 RIGHT JOIN。 ON 子句:用来设置右连接的连接条件,不能省略。 与左连接相反,右连接以”表2”为基表,”表1”为参考表。右连接查询时,可以查询出”表2”中的所有记录和”表1”中匹配连接条件的记录。如果”表2”的某行在”表1”中没有匹配行,那么在返回结果中,”表1”的字段值均为空值(NULL)。
//在tb_course表中新增两条记录
1 2 3 4 5 6 7 8 9 10 11 12 13
mysql> select * from tb_course; +----+-------------+ | id | course_name | +----+-------------+ | 1 | Java | | 2 | MySQL | | 3 | Python | | 4 | Go | | 5 | C++ | | 6 | html | | 7 | shell | +----+-------------+ 7 rows in set (0.00 sec)
例:在 students 表和 tb_course 表中查询所有课程,包括没有学生的课程
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
mysql> select s.name,c.course_name from students s right outer join tb_course c on s.`course_id`=c.`id`; +---------+-------------+ | name | course_name | +---------+-------------+ | Dany | Java | | Green | MySQL | | Henry | Java | | jane | Python | | jim | MySQL | | john | Go | | Lily | Go | | Susan | C++ | | Thomas | C++ | | Tom | C++ | | shiqian | html | | NULL | shell | +---------+-------------+ 12 rows in set (0.00 sec)
在 MySQL 中,GROUP BY 关键字可以根据一个或多个字段对查询结果进行分组。 使用 GROUP BY 关键字的语法格式如下: GROUP BY <字段名> 其中,”字段名”表示需要分组的字段名称,多个字段时用逗号隔开。
GROUP BY单独使用
单独使用 GROUP BY 关键字时,查询结果会只显示每个分组的第一条记录。 例:根据 students 表中的 sex 字段进行分组查询
1 2 3 4 5 6 7 8 9
mysql> select `sex`,count(*) from students group by sex; +-------+----------+ | sex | count(*) | +-------+----------+ | man | 6 | | woman | 5 | +-------+----------+ 2 rows in set (0.00 sec)
GROUP BY 与 GROUP_CONCAT()
GROUP BY 关键字可以和 GROUP_CONCAT() 函数一起使用。GROUP_CONCAT() 函数会把每个分组的字段值都显示出来。 例:根据 students 表中的 sex 字段进行分组查询,使用 GROUP_CONCAT() 函数将每个分组的 name 字段的值都显示出来
1 2 3 4 5 6 7 8 9 10
mysql> select `sex`,group_concat(name) from students group by sex; +-------+------------------------------------+ | sex | group_concat(name) | +-------+------------------------------------+ | man | Dany,Green,jane,Lily,Susan,shiqian | | woman | Henry,jim,john,Thomas,Tom | +-------+------------------------------------+ 2 rows in set (0.00 sec)
mysql> select age,sex,group_concat(name) from students group by age,sex; +------+-------+--------------------+ | age | sex | group_concat(name) | +------+-------+--------------------+ | 20 | man | shiqian | | 21 | woman | john | | 22 | man | jane,Lily,Susan | | 22 | woman | Thomas | | 23 | man | Green | | 23 | woman | Henry,Tom | | 24 | woman | jim | | 25 | man | Dany | +------+-------+--------------------+ 8 rows in set (0.00 sec)
在分组过程中,先按照 age 字段进行分组,当 age 字段值相等时,再把 age 字段值相等的记录按照 sex 字段进行分组。 多个字段分组查询时,会先按照第一个字段进行分组。如果第一个字段中有相同的值,MySQL 才会按照第二个字段进行分组。如果第一个字段中的数据都是唯一的,那么 MySQL 将不再对第二个字段进行分组。
GROUP BY 与聚合函数
在数据统计时,GROUP BY 关键字经常和聚合函数一起使用。 聚合函数包括 COUNT(),SUM(),AVG(),MAX() 和 MIN()。其中,COUNT() 用来统计记录的条数;SUM() 用来计算字段值的总和;AVG() 用来计算字段值的平均值;MAX() 用来查询字段的最大值;MIN() 用来查询字段的最小值。 例:根据 students 表的 sex 字段进行分组查询,使用 COUNT() 函数计算每一组的记录数
1 2 3 4 5 6 7 8 9
mysql> select sex,count(sex) from students group by sex; +-------+------------+ | sex | count(sex) | +-------+------------+ | man | 6 | | woman | 5 | +-------+------------+ 2 rows in set (0.00 sec)
GROUP BY 与 WITH ROLLUP
WITH POLLUP 关键字用来在所有记录的最后加上一条记录,这条记录是上面所有记录的总和,即统计记录数量。 例:根据 students 表中的 sex 字段进行分组查询,并使用 WITH ROLLUP 显示记录的总和
1 2 3 4 5 6 7 8 9 10
mysql> select sex,group_concat(name) from students group by sex with rollup; +-------+--------------------------------------------------------------+ | sex | group_concat(name) | +-------+--------------------------------------------------------------+ | man | Dany,Green,jane,Lily,Susan,shiqian | | woman | Henry,jim,john,Thomas,Tom | | NULL | Dany,Green,jane,Lily,Susan,shiqian,Henry,jim,john,Thomas,Tom | +-------+--------------------------------------------------------------+ 3 rows in set (0.00 sec)
5、子查询
子查询是 MySQL 中比较常用的查询方法,通过子查询可以实现多表查询。子查询指将一个查询语句嵌套在另一个查询语句中。子查询可以在 SELECT、UPDATE 和 DELETE 语句中使用,而且可以进行多层嵌套。在实际开发时,子查询经常出现在 WHERE 子句中。 子查询在 WHERE 中的语法格式如下: WHERE <表达式> <操作符> (子查询) 其中,操作符可以是比较运算符和 IN、NOT IN、EXISTS、NOT EXISTS 等关键字。
例:使用子查询在 students 表和 tb_course 表中查询学习 Java 课程的学生姓名
1 2 3 4 5 6 7 8 9
mysql> select name from students where course_id in (select id from tb_course where course_name = 'Java'); +-------+ | name | +-------+ | Dany | | Henry | +-------+ 2 rows in set (0.00 sec)
mysql> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | mysql | | performance_schema | | sq | | sys | +--------------------+ 5 rows in set (0.00 sec)
mysql> use sq; Database changed mysql> show tables; +--------------+ | Tables_in_sq | +--------------+ | shiqian | | student | | student1 | | students | | tb_course | +--------------+ 5 rows in set (0.00 sec)
[root@mysql ~]# mysqldump -uroot -predhat --all-databases > all-202408031532.sql mysqldump: [Warning] Using a password on the command line interface can be insecure. [root@mysql ~]# ls all-202408031532.sql anaconda-ks.cfg
//备份sq数据库中的students表和tb_course表
1 2 3 4 5 6 7 8 9 10 11
[root@mysql ~]# mysqldump -uroot -predhat --databases sq > sq-202408031745.sql mysqldump: [Warning] Using a password on the command line interface can be insecure. [root@mysql ~]# ls all-202408031532.sql anaconda-ks.cfg sq-202408031745.sql table-202408031735.sql table-202408031737.sql
[root@mysql ~]# mysqldump -uroot -predhat sq tb_course > table-202408031737.sql mysqldump: [Warning] Using a password on the command line interface can be insecure.
[root@mysql ~]# ls all-202408031532.sql anaconda-ks.cfg table-202408031735.sql table-202408031737.sql
mysql> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | mysql | | performance_schema | | sys | +--------------------+ 4 rows in set (0.00 sec)
恢复sq数据库
1 2 3 4 5 6 7 8 9 10 11 12 13 14
[root@mysql ~]# mysql -uroot -p < all-202408031532.sql Enter password: [root@mysql ~]# mysql -uroot -predhat -e 'show databases;' mysql: [Warning] Using a password on the command line interface can be insecure. +--------------------+ | Database | +--------------------+ | information_schema | | mysql | | performance_schema | | sq | | sys | +--------------------+
[root@mysql ~]# mysqldump -uroot -predhat --single-transaction --flush-logs --master-data=2 --all-databases --delete-master-logs > all-202408032134.sql mysqldump: [Warning] Using a password on the command line interface can be insecure. [root@mysql ~]# ls all-202408032134.sql anaconda-ks.cfg
mysql> select * from tb_course; +----+-------------+ | id | course_name | +----+-------------+ | 1 | Java | | 2 | MySQL | | 3 | Python | | 4 | Go | | 5 | C++ | | 6 | html | | 7 | shell | | 7 | NULL | +----+-------------+ 8 rows in set (0.00 sec)
恢复
//模拟误删数据
1 2 3 4 5 6 7 8 9 10 11 12 13
[root@mysql ~]# mysql -uroot -predhat -e 'drop database sq;' mysql: [Warning] Using a password on the command line interface can be insecure. [root@mysql ~]# mysql -uroot -predhat -e 'show databases;' mysql: [Warning] Using a password on the command line interface can be insecure. +--------------------+ | Database | +--------------------+ | information_schema | | mysql | | performance_schema | | sys | +--------------------+
[root@mysql ~]# ll /opt/data/ total 123004 -rw-r-----. 1 mysql mysql 56 Jul 30 16:29 auto.cnf -rw-------. 1 mysql mysql 1680 Jul 30 16:29 ca-key.pem -rw-r--r--. 1 mysql mysql 1112 Jul 30 16:29 ca.pem -rw-r--r--. 1 mysql mysql 1112 Jul 30 16:29 client-cert.pem -rw-------. 1 mysql mysql 1676 Jul 30 16:29 client-key.pem -rw-r-----. 1 mysql mysql 901 Aug 3 19:49 ib_buffer_pool -rw-r-----. 1 mysql mysql 12582912 Aug 3 20:14 ibdata1 -rw-r-----. 1 mysql mysql 50331648 Aug 3 20:14 ib_logfile0 -rw-r-----. 1 mysql mysql 50331648 Jul 30 16:29 ib_logfile1 -rw-r-----. 1 mysql mysql 12582912 Aug 3 20:04 ibtmp1 drwxr-x---. 2 mysql mysql 4096 Aug 3 17:44 mysql -rw-r-----. 1 mysql mysql 844 Aug 3 20:14 mysql_bin.000002 -rw-r-----. 1 mysql mysql 19 Aug 3 20:04 mysql_bin.index -rw-r-----. 1 mysql mysql 41336 Aug 3 19:49 mysql.example.com.err -rw-r-----. 1 mysql mysql 5 Aug 3 19:49 mysql.pid drwxr-x---. 2 mysql mysql 8192 Jul 30 16:29 performance_schema -rw-------. 1 mysql mysql 1680 Jul 30 16:29 private_key.pem -rw-r--r--. 1 mysql mysql 452 Jul 30 16:29 public_key.pem -rw-r--r--. 1 mysql mysql 1112 Jul 30 16:29 server-cert.pem -rw-------. 1 mysql mysql 1680 Jul 30 16:29 server-key.pem drwxr-x---. 2 mysql mysql 8192 Jul 30 16:29 sys [root@mysql ~]# mysqladmin -uroot -predhat flush-logs mysqladmin: [Warning] Using a password on the command line interface can be insecure. [root@mysql ~]# ll /opt/data/ total 123008 -rw-r-----. 1 mysql mysql 56 Jul 30 16:29 auto.cnf -rw-------. 1 mysql mysql 1680 Jul 30 16:29 ca-key.pem -rw-r--r--. 1 mysql mysql 1112 Jul 30 16:29 ca.pem -rw-r--r--. 1 mysql mysql 1112 Jul 30 16:29 client-cert.pem -rw-------. 1 mysql mysql 1676 Jul 30 16:29 client-key.pem -rw-r-----. 1 mysql mysql 901 Aug 3 19:49 ib_buffer_pool -rw-r-----. 1 mysql mysql 12582912 Aug 3 20:16 ibdata1 -rw-r-----. 1 mysql mysql 50331648 Aug 3 20:16 ib_logfile0 -rw-r-----. 1 mysql mysql 50331648 Jul 30 16:29 ib_logfile1 -rw-r-----. 1 mysql mysql 12582912 Aug 3 20:04 ibtmp1 drwxr-x---. 2 mysql mysql 4096 Aug 3 17:44 mysql -rw-r-----. 1 mysql mysql 891 Aug 3 20:16 mysql_bin.000002 -rw-r-----. 1 mysql mysql 154 Aug 3 20:16 mysql_bin.000003 -rw-r-----. 1 mysql mysql 38 Aug 3 20:16 mysql_bin.index -rw-r-----. 1 mysql mysql 41336 Aug 3 19:49 mysql.example.com.err -rw-r-----. 1 mysql mysql 5 Aug 3 19:49 mysql.pid drwxr-x---. 2 mysql mysql 8192 Jul 30 16:29 performance_schema -rw-------. 1 mysql mysql 1680 Jul 30 16:29 private_key.pem -rw-r--r--. 1 mysql mysql 452 Jul 30 16:29 public_key.pem -rw-r--r--. 1 mysql mysql 1112 Jul 30 16:29 server-cert.pem -rw-------. 1 mysql mysql 1680 Jul 30 16:29 server-key.pem drwxr-x---. 2 mysql mysql 8192 Jul 30 16:29 sys
[root@mysql ~]# mysql -uroot -predhat < all-202408032134.sql mysql: [Warning] Using a password on the command line interface can be insecure. [root@mysql ~]# mysql -uroot -predhat -e 'show databases;' mysql: [Warning] Using a password on the command line interface can be insecure. +--------------------+ | Database | +--------------------+ | information_schema | | mysql | | performance_schema | | sq | | sys | +--------------------+
[root@mysql ~]# mysql -uroot -predhat -e 'select * from sq.students;' mysql: [Warning] Using a password on the command line interface can be insecure. +----+---------+------+-------+--------+-----------+ | id | name | age | sex | height | course_id | +----+---------+------+-------+--------+-----------+ | 1 | Dany | 25 | man | 160 | 1 | | 2 | Green | 23 | man | 158 | 2 | | 3 | Henry | 23 | woman | 185 | 1 | | 4 | jane | 22 | man | 162 | 3 | | 5 | jim | 24 | woman | 175 | 2 | | 6 | john | 21 | woman | 172 | 4 | | 7 | Lily | 22 | man | 188 | 4 | | 8 | Susan | 22 | man | 179 | 5 | | 9 | Thomas | 22 | woman | 158 | 5 | | 10 | Tom | 23 | woman | 165 | 5 | | 11 | shiqian | 20 | man | 188 | 6 | +----+---------+------+-------+--------+-----------+ [root@mysql ~]# mysql -uroot -predhat -e 'select * from sq.tb_course;' mysql: [Warning] Using a password on the command line interface can be insecure. +----+-------------+ | id | course_name | +----+-------------+ | 1 | Java | | 2 | MySQL | | 3 | Python | | 4 | Go | | 5 | C++ | | 6 | html | | 7 | shell | +----+-------------+