MySQL的基本学习(三)——DD/M/QL三类SQL语言和SQLyog

前言

好久没有学MySQL了,最近因为JavaWeb的原因,让我正好在补习一下SQL语句等知识,SQL语句虽然在这系列的第一篇文章里聊过了,但是这篇文章里我计划重新学一下


DDL

Data Definition Language,数据定义语言,用来定义数据库对象

DDL主要用来操作数据库和数据库的表。

所谓操作,主要就是四个:CRUD

  1. C(Create):创建
  2. R(Retrieve):查询
  3. U(Update):修改
  4. D(Delete):删除

操作数据库

R(Retrieve):查询

  • 查询所有数据库的名称: SHOW DATABASES;
mysql> SHOW DATABASES;
+--------------------+
| Database           |
+--------------------+
| crazythings        |
| information_schema |
| jsptest            |
| mysql              |
| notenow            |
| performance_schema |
+--------------------+
6 rows in set (0.01 sec)

performance_schema、mysql、test(我删了这个了)、information_schema 这四个数据库是MySQL自带的数据库:

  1. information_schema :你在数据目录下的data目录中找不到这个information_schema 目录,因为这个数据库不是真正的数据库,它只是用来描述MySQL中的一些信息的(例如有哪些表、有哪些库的名字),这里面存放的表并不是真正的表,而是视图(以后学习的玩意儿),该数据库并不存在真正对应的物理文件
  2. mysql:核心数据库,存放了很多核心数据
  3. performance_schema:对性能提升相关的数据库
  4. test:想删就删,测试库而已
  • 查询创建数据库的语法:SHOW CREATE DATABASE 库名;
mysql> SHOW CREATE DATABASE notenow;
+----------+---------------------------------------------------- -------------+
| Database | Create Database                                                  |
+----------+------------------------------------------------------------------+
| notenow  | CREATE DATABASE `notenow` /*!40100 DEFAULT CHARACTER SET utf8 */ |
+----------+---------------------------------------------------------- -------+
1 row in set (0.00 sec)

数据库默认使用的是utf-8字符集。

C(Create):创建

  • 创建数据库:CREATE DATABASE 数据库名;
mysql> CREATE DATABASE DB1;
Query OK, 1 row affected (0.02 sec)
  • 创建数据库:CREATE DATABASE IF NOT EXISTS 数据库名;
mysql> CREATE DATABASE IF NOT EXISTS DB2;
Query OK, 1 row affected (0.02 sec)

这种创建数据库与上面的区别在于:上面的创建语句,如果已经存在同名数据库,则会报错;该语句,如果存在同名数据库不会报错,也不会去创建,如果没有同名数据库才会创建。

  • 创建数据库并指定字符集:CREATE DATABASE 数据库名 CHARACTER SET 字符集;
mysql> CREATE DATABASE DB3 CHARACTER SET gbk;
Query OK, 1 row affected (0.02 sec)

“SHOW CREATE DATABASE 库名” 查看数据库字符集。

综合利用:创建一个数据库且指定字符集为utf-8,且有重名的话不能报错。

CREATE DATABASE IF NOT EXISTS DB4 CHARACTER SET utf8;

U(Update):修改

  • 修改数据库字符集:ALTER DATABASE 数据库名称 CHARACTER SET 字符集;
mysql> ALTER DATABASE DB3 CHARACTER SET utf8;
Query OK, 1 row affected, 1 warning (0.00 sec)

D(Delete):删除

  • 删除数据库:DROP DATABASE 数据库名称;
mysql> DROP DATABASE DB3;
Query OK, 0 rows affected (0.02 sec)
  • 删除数据库:DROP DATABASE IF EXISTS 数据库名称;
mysql> DROP DATABASE IF EXISTS DB3;
Query OK, 0 rows affected (0.02 sec)

这种删除数据库与上面的区别在于:上面的删除语句,如果没有该数据库,则会报错;该语句,如果不存在该数据库不会报错,当然也不会去删除,如果存在数据库才会删除。这个与CREATE那里的道理类似。

使用数据库

  • 查询当前正在使用的数据库的名称:SELECT DATABASE();
mysql> SELECT DATABASE();
+--------------------+
| DATABASE()         |
+--------------------+
| information_schema |
+--------------------+
1 row in set (0.00 sec)
  • 使用数据库:USE 数据库名称;

操作数据表

C(Create):创建

  • 创建表:CREATE  TABLE  表名  ( 列名1 数据类型1,列名2 数据类型2,列名3 数据类型3 );
mysql> CREATE TABLE student(-> id int,-> name varchar(32),-> age int,-> score double(4,1),-> birthday date,-> insert_time timestamp-> );
Query OK, 0 rows affected, 1 warning (0.04 sec)

常见数据库数据类型:

  1. int:整数类型,示例:age  int
  2. double:小数类型(双精度浮点数),示例:score  double(5,2) ——括号意为小数点后最多5位,我们保留两位
  3. date:日期,只包含年月日,yyyy-MM-dd
  4. datetime:日期,包含年月日时分秒,yyyy-MM-dd HH:mm:ss
  5. timestamp:时间戳类型,包含年月日时分秒,yyyy-MM-dd HH:mm:ss,与datetime区别,如果不给这个timestamp字段赋值或者赋值为null,那么它将会默认使用当前的系统时间,来自动赋值
  6. varchar:字符串类型,示例:name varchar(20)——默认后面最大20个字符

注意,最后一个字段信息末尾不需要加逗号

  • 复制一个数据表:CREATE  TABLE  新表名  LIKE  被复制表名
mysql> CREATE TABLE stu LIKE student;
Query OK, 0 rows affected, 1 warning (0.03 sec)

R(Retrieve):查询

  • 查询某个数据库中所有的表的名称:SHOW TABLES;
mysql> SHOW TABLES;
+-------------------+
| Tables_in_notenow |
+-------------------+
| test              |
| worker            |
+-------------------+
2 rows in set (0.00 sec)
  • 查询表结构:DESC 表名;
mysql> DESC worker;
+-----------+-------------+------+-----+---------+-------+
| Field     | Type        | Null | Key | Default | Extra |
+-----------+-------------+------+-----+---------+-------+
| 职工号    | int(11)     | NO   | PRI | NULL    |       |
| 姓名      | varchar(20) | YES  |     | NULL    |       |
| 性别      | varchar(2)  | YES  |     | NULL    |       |
| 工资      | int(11)     | YES  |     | NULL    |       |
| 职称      | varchar(20) | YES  |     | NULL    |       |
+-----------+-------------+------+-----+---------+-------+
5 rows in set (0.00 sec)

U(Update):修改

  • 修改表名:ALTER  TABLE  表名  RENAME  TO  新表名;
mysql> ALTER TABLE stu RENAME TO student;
Query OK, 0 rows affected (0.03 sec)
  • 修改表的字符集:ALTER  TABLE  student  CHARACTER  SET  utf8;

“SHOW CREATE TABLE student;”查看表以前的字符集

  • 添加一个字段:ALTER  TABLE  表名  ADD  字段名  数据类型;
mysql> ALTER TABLE student ADD sex varchar(10);
Query OK, 0 rows affected (0.02 sec)
Records: 0  Duplicates: 0  Warnings: 0
  • 修改字段名称、类型:ALTER  TABLE  表名  CHANGE  字段  新字段  新字段数据类型;
mysql> ALTER TABLE student CHANGE sex gender varchar(20);
Query OK, 0 rows affected (0.02 sec)
Records: 0  Duplicates: 0  Warnings: 0
  • 修改字段类型:ALTER  TABLE  表名  MODIFY  字段名  新数据类型
mysql> ALTER TABLE student  MODIFY  gender  varchar(10);
Query OK, 0 rows affected (0.05 sec)
Records: 0  Duplicates: 0  Warnings: 0
  • 删除字段:ALTER  TABLE  表名  DROP  字段名
mysql> ALTER TABLE student DROP gender;
Query OK, 0 rows affected (0.04 sec)
Records: 0  Duplicates: 0  Warnings: 0

D(Delete):删除

  • 删除数据表:DROP  TABLE  表名;
mysql> DROP TABLE student;
Query OK, 0 rows affected (0.02 sec)
  • 删除数据表:DROP  TABLE IF  EXISTS  表名;

存在,则删除、不存在,也不会报错。


插曲:SQLyog

为了方便我们使用数据库MySQL,这里我们来使用一个图形化操作的工具SQLyog

分享链接:https://pan.baidu.com/s/1KJarOpABTpIR76yZGHOVTQ
提取码:1d5u

一路下一步安装即可

然后打开后会要求注册序列号,sn.txt中随便写一个即可。

然后就可以成功打开了,然后会弹出一个连接到我的SQL主机,新建,配置用户名、密码,连接即可。

配置新连接报错:错误号码 2058,分析是 mysql 密码加密方法变了。

解决方式:先登录你的数据库,然后执行

ALTER USER ‘root’@’localhost’ IDENTIFIED WITH mysql_native_password BY ‘password’;

password是你的登陆密码。

正如workBench、Navicat等图形化工具一样,这类工具非常方便,很多操作可以直接点击实现,不需要输入SQL语句,不过在我们学习阶段,还是建议老老实实使用SQL语句去操作。


DML

Data Manipulation Language,数据操作语言,用来对数据库中表的数据进行增删改。

主要用来增删表中的数据,是非常重要的SQL语言。

DML主要是针对数据表中的数据,这个主要分为三个方面:添加数据、删除数据、修改数据

操作数据

添加数据

  • 添加数据:INSERT  INTO  表名(字段1,字段2,……,字段n)  VALUES(值1,值2,……,值n);
mysql> INSERT INTO test(id,name,password) VALUES(5,'张无忌','987654321');
Query OK, 1 row affected (0.02 sec)

注意点:

  1. 列名和值要一一对应
  2. 除了数字类型以外,其他类型需要使用引号(单双都可以)。
  • 添加数据:INSERT  INTO  表名  VALUES(值1,值2,……,值n);
mysql> INSERT INTO test VALUES(5,'赵敏','123456789');
Query OK, 1 row affected (0.02 sec)

这条语句和上一句的区别在于:表名后面没有说明字段,则给所有字段依次添加值,如果想要空开,可以使用“NULL”,如果对应字段数据类型是时间戳timestamp,则会自动填入当前时间。

删除数据

  • 删除数据:DELETE  FROM  表名 [WHERE 条件]
mysql> DELETE FROM test WHERE name='张无忌';
Query OK, 1 row affected (0.01 sec)

注意:如果不添加条件,那么会将表中的记录全部删除!!!

  • 删除表,然后再创建一个一模一样的空表:TRUNCATE  TABLE  表名;
mysql> TRUNCATE TABLE test;
Query OK, 0 rows affected (0.03 sec)

如果你想要删除一个表中的所有记录,建议使用TRUNBLE TABLE,而不是DELETE  FROM  表名,因为后者会根据数据记录数量执行同等数量的指令,对性能不友好;而TRUNBLE TABLE,只会执行“DROP”删除表、“CREATE” 创建表,两个指令,性能更佳。

老实说我不知道这个命令应该属于DDL(数据定义语言),还是DML(数据操作语言)

修改数据

  • UPDATE  表名  SET  列名1=值1,列名2=值2,……,列名n=值n   [WHERE  条件];
mysql> UPDATE test SET password=567 WHERE id=3;
Query OK, 1 row affected (0.01 sec)

注意:如果不添加任何条件,则会将表中所有记录根据字段全部修改。


DQL

Data Query Language,数据查询语言,用来对数据库中表的数据进行查询。

基础查询

基本使用

查询数据:SELECT  *  FROM  表名;

语法:

SELECT   字段列表

FROM   表名列表

[WHERE  条件列表]

[GROUP  BY  分组字段 ]

[HAVING  分组之后的条件]

[ORDER  BY  排序]

[LIMIT  分页限定]

mysql> select * from test;
+----+-----------------+-----------+
| id | name            | password  |
+----+-----------------+-----------+
|  1 | 可爱的兔子      | 123456    |
|  2 | 凶恶的老虎      | 654321    |
|  3 | 职工号          | 12345     |
|  5 | 张无忌          | 987654321 |
+----+-----------------+-----------+
4 rows in set (0.00 sec)
//查询指定字段
mysql> SELECT name,sex FROM test;
+--------+------+
| name   | sex  |
+--------+------+
| 小红   | 女   |
| 小明   | 男   |
| 小张   | 男   |
| 小浅   | 女   |
| 小军   | 男   |
| 小候   | 男   |
| 阿炜   | 男   |
| 小丽   | 女   |
+--------+------+
8 rows in set (0.00 sec)

去重

查询结果经常会用来去重,例如男女、地名等,没有必要显示很多相同的。

语法:加入 DISTINCT 关键字

mysql> SELECT DISTINCT sex FROM test;
+------+
| sex  |
+------+
| 女   |
| 男   |
+------+
2 rows in set (0.00 sec)

去重的话要保证结果集完全一样,即多个字段完全一样才能叫做重复。

计算

字段中直接设置一个“和字段”即可

mysql> SELECT name,math,english,math+english FROM test;
+--------+------+---------+--------------+
| name   | math | english | math+english |
+--------+------+---------+--------------+
| 小王   |   56 |      57 |          113 |
| 小李   |   85 |      78 |          163 |
| 小赵   |   25 |      38 |           63 |
+--------+------+---------+--------------+
3 rows in set (0.00 sec)

注意:如果有null,参与的运算,计算的结果都为null,如果不符合实际情况,可以结合函数IFNUll处理,例如上例加成绩:SELECT name,math,english,math+IFNULL(english,0) FROM test;,即如果英语成绩为NULL,则替换为0。

另外,对于字段 math+english,如果觉得难看,可以起一个别名,语法:SELECT name,math,english,math+english  AS   总分    FROM test; 即可,也可以省略AS关键字,其他字段math、english也可以这样修改

mysql> SELECT name,math,english,math+english  AS 总分 FROM test;
+--------+------+---------+--------+
| name   | math | english | 总分   |
+--------+------+---------+--------+
| 小王   |   56 |      57 |    113 |
| 小李   |   85 |      78 |    163 |
| 小赵   |   25 |      38 |     63 |
+--------+------+---------+--------+
3 rows in set (0.00 sec)

不过一般别名都会使用英文的。

条件查询

语法: WHERE   条件

使用示例:

mysql> SELECT name,math FROM test WHERE math>=56;
+--------+------+
| name   | math |
+--------+------+
| 小王   |   56 |
| 小李   |   85 |
+--------+------+
2 rows in set (0.00 sec)
//可以使用&&、AND,或者 BETWEEN  AND
mysql> SELECT name,math FROM test WHERE english  BETWEEN 60 AND 100;
+--------+------+
| name   | math |
+--------+------+
| 小李   |   85 |
+--------+------+
1 row in set (0.00 sec)
mysql> SELECT * FROM test WHERE math IN(85,25);
+----+--------+---------+------+
| id | name   | english | math |
+----+--------+---------+------+
|  2 | 小李   |      78 |   85 |
|  3 | 小赵   |      38 |   25 |
+----+--------+---------+------+
2 rows in set (0.00 sec)

常用SQL运算符:

比较运算符 说明
>、<、<=、>=、=、<> 其中,<>在SQL中表示不等于,在mysql中也可以使用!=,但是SQL中没有==运算符
BETWEEN…AND 在一个范围之内,如BETWEEN 100 AND 200,相当于条件在100到200之间,包头且包尾
IN(集合) 集合表示多个值,使用逗号分隔
LIKE ‘关键字’ 模糊查询
IS NULL 查询某一列为NULL的值(不能写 =NULL)
IS NOT NULL 查询某一列不为NULL的值
逻辑运算符 说明
and 或 && 与,SQL中建议使用前者,后者不通用
or 或 ||
not 或 !

模糊查询

模糊查询比较牛逼,我们单独来说。

条件查询中的模糊查询使用关键字LIKE,需要注意的点:

  • 占位符

    • _:单个任意字符(一个)
    • %:多个任意字符(0或者多个)
mysql> SELECT * FROM test;
+----+--------------+---------+------+
| id | name         | english | math |
+----+--------------+---------+------+
|  1 | 慕容复       |      56 |   46 |
|  2 | 东方不败     |      47 |   58 |
|  3 | 令狐冲       |      56 |   38 |
|  4 | 张无忌       |      16 |   20 |
|  5 | 慕容博       |      78 |   90 |
|  6 | 孤独求败     |      53 |   49 |
|  7 | 张三丰       |      67 |   66 |
+----+--------------+---------+------+
7 rows in set (0.00 sec)mysql> SELECT id,name FROM test WHERE name LIKE '张%';
+----+-----------+
| id | name      |
+----+-----------+
|  4 | 张无忌    |
|  7 | 张三丰    |
+----+-----------+
2 rows in set (0.00 sec)mysql> SELECT id,name FROM test WHERE name LIKE '慕容_';
+----+-----------+
| id | name      |
+----+-----------+
|  1 | 慕容复    |
|  5 | 慕容博    |
+----+-----------+
2 rows in set (0.00 sec)mysql> SELECT id,name FROM test WHERE name LIKE '%败';
+----+--------------+
| id | name         |
+----+--------------+
|  2 | 东方不败     |
|  6 | 孤独求败     |
+----+--------------+
2 rows in set (0.00 sec)

如果出现异常,可能是数据里存在空字符

排序查询

语法:ORDER BY  字句

具体使用:ORDER BY  排序字段1  排序方式1,排序字段2  排序方式2,排序字段3  排序方式3

单一排序条件

mysql> SELECT * FROM test ORDER BY id ASC;
+----+--------+----------+
| id | name   | password |
+----+--------+----------+
|  1 | 乔峰   | 123      |
|  2 | 段誉   | 234      |
|  3 | 虚竹   | 345      |
+----+--------+----------+
3 rows in set (0.00 sec)mysql> SELECT * FROM test ORDER BY id DESC;
+----+--------+----------+
| id | name   | password |
+----+--------+----------+
|  3 | 虚竹   | 345      |
|  2 | 段誉   | 234      |
|  1 | 乔峰   | 123      |
+----+--------+----------+
3 rows in set (0.00 sec)

排序方式:

  1. ASC:升序(默认)
  2. DESC:降序

学英语
ascend:上升、升高
descend:下降

多排序条件

如果第一排序条件相同,那么数据库会根据第二排序条件进行排序,例如示例数学成绩相同,根据英语成绩升序排列:

mysql> SELECT * FROM score ORDER BY math ASC,english ASC;
+------+-----------+------+---------+
| id   | name      | math | english |
+------+-----------+------+---------+
|    3 | 郭富城    |   69 |      34 |
|    2 | 刘德华    |   77 |      81 |
|    1 | 张学友    |   77 |      85 |
|    4 | 黎明      |   90 |      87 |
+------+-----------+------+---------+
4 rows in set (0.00 sec)

聚合查询

聚合函数:将一列数据作为一个整体,然后进行纵向的计算

例如上例,计算四大天王的math的总成绩,就可以使用聚合函数

可用聚合函数:

  1. count:计算个数
  2. max:计算最大值
  3. min:计算最小值
  4. sum:求和
  5. avg:计算平均值

语法:SELECT  函数(字段)    FROM  表名;

注意:聚合函数会排除NULL的数据,解决方法可以利用IFNULL函数,例如SELECT  COUNT(IFNULL(english,0))  FROM  student,即student表中的english字段中,将NULL替换成0,然后统计english字段下的个数。

mysql> SELECT AVG(math) FROM score;
+-----------+
| AVG(math) |
+-----------+
|     78.25 |
+-----------+
1 row in set (0.01 sec)

分组查询

分组查询意为根据字段的值,将数据分组,然后根据分组进行处理。

语法:GROUP BY 分组字段

mysql> SELECT* FROM test;
+----+--------+-------+------+
| id | name   | score | sex  |
+----+--------+-------+------+
|  1 | 小红   |    59 | 女   |
|  2 | 小明   |    15 | 男   |
|  3 | 小张   |    87 | 男   |
|  4 | 小浅   |    79 | 女   |
+----+--------+-------+------+
4 rows in set (0.00 sec)
//示例,将分数按照男女分组
mysql> SELECT  sex,AVG(score)  FROM test GROUP BY sex;
+------+------------+
| sex  | AVG(score) |
+------+------------+
| 女   |    69.0000 |
| 男   |    51.0000 |
+------+------------+
2 rows in set (0.01 sec)//进阶示例:将分数按照男女分组,且不计入低于60分的同学
mysql> SELECT  sex,AVG(score)  FROM test WHERE score>60 GROUP BY sex;
+------+------------+
| sex  | AVG(score) |
+------+------------+
| 男   |    87.0000 |
| 女   |    79.0000 |
+------+------------+
2 rows in set (0.00 sec)//进阶示例,分组后,显示多于一个人的组的情况
mysql> SELECT  sex,AVG(score)  FROM test  GROUP BY sex HAVING COUNT(id)>1;
+------+------------+
| sex  | AVG(score) |
+------+------------+
| 女   |    69.0000 |
| 男   |    51.0000 |
+------+------------+
2 rows in set (0.00 sec)

注意:

  1. 分组之后查询的字段:分组字段、聚合函数
  2. WHERE和HAVING的区别:
    1. WHERE在分组之前进行限定,如果不满足条件则不参与分组;HAVING在分组之后进行限定,如果不满足结果则不会被查询出来。
    2. WHERE后面不可以跟聚合函数,HAVING后面可以跟着聚合函数。

补充,对于HAVING的使用可以采用“别名”的机制来使命令简洁:

//给聚合函数COUNT(id)起一个别名,在后面HAVING后面可以直接使用别名代替
mysql> SELECT  sex,COUNT(id) num  FROM test  GROUP BY sex HAVING num>1;
+------+-----+
| sex  | num |
+------+-----+
| 女   |   2 |
| 男   |   2 |
+------+-----+
2 rows in set (0.00 sec)

分页查询

语法:LIMIT 开始的索引,每页查询的条数;

mysql> SELECT * FROM test;
+----+--------+-------+------+
| id | name   | score | sex  |
+----+--------+-------+------+
|  1 | 小红   |    59 | 女   |
|  2 | 小明   |    15 | 男   |
|  3 | 小张   |    87 | 男   |
|  4 | 小浅   |    79 | 女   |
|  5 | 小军   |    68 | 男   |
|  6 | 小候   |    77 | 男   |
|  7 | 阿炜   |    59 | 男   |
|  8 | 小丽   |    63 | 女   |
+----+--------+-------+------+
8 rows in set (0.00 sec)mysql> SELECT * FROM test LIMIT 0,3;
+----+--------+-------+------+
| id | name   | score | sex  |
+----+--------+-------+------+
|  1 | 小红   |    59 | 女   |
|  2 | 小明   |    15 | 男   |
|  3 | 小张   |    87 | 男   |
+----+--------+-------+------+
3 rows in set (0.00 sec)mysql> SELECT * FROM test LIMIT 3,3;
+----+--------+-------+------+
| id | name   | score | sex  |
+----+--------+-------+------+
|  4 | 小浅   |    79 | 女   |
|  5 | 小军   |    68 | 男   |
|  6 | 小候   |    77 | 男   |
+----+--------+-------+------+
3 rows in set (0.00 sec)mysql> SELECT * FROM test LIMIT 6,3;
+----+--------+-------+------+
| id | name   | score | sex  |
+----+--------+-------+------+
|  7 | 阿炜   |    59 | 男   |
|  8 | 小丽   |    63 | 女   |
+----+--------+-------+------+
2 rows in set (0.00 sec)

公式:开始的索引=(当前的页码-1)*每页显示的条数

注意:

  1. 数据库中的数据的索引是从0开始的
  2. 最后一页如果不满足要求显示条数,那么将有多少条就显示多少条
  3. 分页操作是一个“方言”,即别的数据库软件可能会有出入,LIMIT这个子句仅限于MySQL

多表查询(属于DQL的知识点)

概述

基本语法:SELECT  字段列表  FROM  表名列表  WHERE  条件

我们来造两个表,跟着我做:

Dept:部门

 CREATE TABLE dept(id INT PRIMARY KEY AUTO_INCREMENT,name VARCHAR(20)
);INSERT INTO dept (name) VALUES('开发部'),
('市场部'),
('财务部');

emp:员工

CREATE TABLE emp(
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(10),
gender CHAR(1),
salary DOUBLE,
join_date DATE,
dept_id INT,
FOREIGN KEY (dept_id) REFERENCES dept(id)
);INSERT INTO emp(name,gender,salary,join_date,dept_id)
VALUES('孙悟空','男',7200,'2013-02-24',1);INSERT INTO emp(name,gender,salary,join_date,dept_id)
VALUES('猪八戒','男',3600,'2012-07-04',2);INSERT INTO emp(name,gender,salary,join_date,dept_id)
VALUES('唐僧','男',9000,'2015-01-29',2);INSERT INTO emp(name,gender,salary,join_date,dept_id)
VALUES('白骨精','女',3000,'2010-04-20',3);INSERT INTO emp(name,gender,salary,join_date,dept_id)
VALUES('蜘蛛精','女',6500,'2016-07-25',1);

最终两个表的内容:

mysql> SELECT * FROM dept;
+----+-----------+
| id | name      |
+----+-----------+
|  1 | 开发部    |
|  2 | 市场部    |
|  3 | 财务部    |
+----+-----------+
3 rows in set (0.00 sec)mysql> SELECT * FROM emp;
+----+-----------+--------+--------+------------+---------+
| id | name      | gender | salary | join_date  | dept_id |
+----+-----------+--------+--------+------------+---------+
|  1 | 孙悟空    | 男     |   7200 | 2013-02-24 |       1 |
|  2 | 猪八戒    | 男     |   3600 | 2012-07-04 |       2 |
|  3 | 唐僧      | 男     |   9000 | 2015-01-29 |       2 |
|  4 | 白骨精    | 女     |   3000 | 2010-04-20 |       3 |
|  5 | 蜘蛛精    | 女     |   6500 | 2016-07-25 |       1 |
+----+-----------+--------+--------+------------+---------+
5 rows in set (0.00 sec)

操作示例

执行语句SELECT  *  FROM  emp,dept

mysql> SELECT * FROM emp,dept;
+----+-----------+--------+--------+------------+---------+----+-----------+
| id | name      | gender | salary | join_date  | dept_id | id | name      |
+----+-----------+--------+--------+------------+---------+----+-----------+
|  1 | 孙悟空    | 男     |   7200 | 2013-02-24 |       1 |  1 | 开发部    |
|  1 | 孙悟空    | 男     |   7200 | 2013-02-24 |       1 |  2 | 市场部    |
|  1 | 孙悟空    | 男     |   7200 | 2013-02-24 |       1 |  3 | 财务部    |
|  2 | 猪八戒    | 男     |   3600 | 2012-07-04 |       2 |  1 | 开发部    |
|  2 | 猪八戒    | 男     |   3600 | 2012-07-04 |       2 |  2 | 市场部    |
|  2 | 猪八戒    | 男     |   3600 | 2012-07-04 |       2 |  3 | 财务部    |
|  3 | 唐僧      | 男     |   9000 | 2015-01-29 |       2 |  1 | 开发部    |
|  3 | 唐僧      | 男     |   9000 | 2015-01-29 |       2 |  2 | 市场部    |
|  3 | 唐僧      | 男     |   9000 | 2015-01-29 |       2 |  3 | 财务部    |
|  4 | 白骨精    | 女     |   3000 | 2010-04-20 |       3 |  1 | 开发部    |
|  4 | 白骨精    | 女     |   3000 | 2010-04-20 |       3 |  2 | 市场部    |
|  4 | 白骨精    | 女     |   3000 | 2010-04-20 |       3 |  3 | 财务部    |
|  5 | 蜘蛛精    | 女     |   6500 | 2016-07-25 |       1 |  1 | 开发部    |
|  5 | 蜘蛛精    | 女     |   6500 | 2016-07-25 |       1 |  2 | 市场部    |
|  5 | 蜘蛛精    | 女     |   6500 | 2016-07-25 |       1 |  3 | 财务部    |
+----+-----------+--------+--------+------------+---------+----+-----------+
15 rows in set (0.00 sec)

很牛逼,突然就有了这么多的数据。

其实这个结果集,有另外一个称呼“笛卡尔积”,即有两个集合A、B,A、B集合中所有成员的组合情况就称为笛卡尔积。

上面的数据中,我们的emp表中的dept_id 属性代表该员工所属哪个部门,这个值应该与dept表中的id相同才有必要显示,换句话说就是,我们需要消除不必要的查询数据。

这就需要我们进行多表查询的分类,从而消除无用数据:

多表查询的分类

内连接查询

  • 隐式内连接:使用WHERE条件来消除无用的数据

以上例为例,我们要查询所有员工的信息和对应部门的信息:

mysql> SELECT * FROM emp,dept WHERE emp.`dept_id`=dept.`id`;
+----+-----------+--------+--------+------------+---------+----+-----------+
| id | name      | gender | salary | join_date  | dept_id | id | name      |
+----+-----------+--------+--------+------------+---------+----+-----------+
|  1 | 孙悟空    | 男     |   7200 | 2013-02-24 |       1 |  1 | 开发部    |
|  5 | 蜘蛛精    | 女     |   6500 | 2016-07-25 |       1 |  1 | 开发部    |
|  2 | 猪八戒    | 男     |   3600 | 2012-07-04 |       2 |  2 | 市场部    |
|  3 | 唐僧      | 男     |   9000 | 2015-01-29 |       2 |  2 | 市场部    |
|  4 | 白骨精    | 女     |   3000 | 2010-04-20 |       3 |  3 | 财务部    |
+----+-----------+--------+--------+------------+---------+----+-----------+
5 rows in set (0.00 sec)

注意:在WHERE后面使用“表名.`字段`”来指出参与比较的字段,字段左右是反单引号,不是单引号,不过其实加不加都可以。

如果我们只是想要得到几个字段的内容,也需要指出字段所属哪个表:

mysql> SELECT emp.`name`,emp.`gender`,dept.`name`  FROM emp,dept WHERE emp.dept_id=dept.id;
+-----------+--------+-----------+
| name      | gender | name      |
+-----------+--------+-----------+
| 孙悟空    | 男     | 开发部    |
| 蜘蛛精    | 女     | 开发部    |
| 猪八戒    | 男     | 市场部    |
| 唐僧      | 男     | 市场部    |
| 白骨精    | 女     | 财务部    |
+-----------+--------+-----------+
5 rows in set (0.00 sec)

重复输好几次表名不免有些繁琐,所以一般我们来进行多表的处理的话,会给表起个别名,并且在写的时候要注意分行,方便我们以后加注释等操作。

mysql> SELECT-> t1.name,-> t1.gender,-> t2.name  -- 部门的名称-> FROM-> emp t1,-> dept t2-> WHERE-> t1.`dept_id` = t2.`id`;
+-----------+--------+-----------+
| name      | gender | name      |
+-----------+--------+-----------+
| 孙悟空    | 男     | 开发部    |
| 蜘蛛精    | 女     | 开发部    |
| 猪八戒    | 男     | 市场部    |
| 唐僧      | 男     | 市场部    |
| 白骨精    | 女     | 财务部    |
+-----------+--------+-----------+
5 rows in set (0.00 sec)
  • 显式内连接:基本语法–  SELECT  字段列表  FROM  表名  [INNER] JOIN  表名2  ON  条件
mysql> SELECT-> t1.name,-> t1.gender,-> t2.name-> FROM-> emp t1  -- 起别名-> INNER JOIN  -- INNER可以省略-> dept t2  -- 起别名-> ON  -- 限制条件-> t1.`dept_id` = t2.`id`;
+-----------+--------+-----------+
| name      | gender | name      |
+-----------+--------+-----------+
| 孙悟空    | 男     | 开发部    |
| 蜘蛛精    | 女     | 开发部    |
| 猪八戒    | 男     | 市场部    |
| 唐僧      | 男     | 市场部    |
| 白骨精    | 女     | 财务部    |
+-----------+--------+-----------+
5 rows in set (0.00 sec)

内连接显式查询中,INNER这个关键字是可以省略的。

总结: 内连接显式查询的是两表其交集的部分(是否交集由条件ON判断)

  • 内连接查询注意事项:

    • 从哪些表中查询数据
    • 查询条件是什么
    • 查询哪些字段

外连接查询

  • 左外连接:语法– SELECT  字段列表  FROM  表1  LEFT  [OUTER]  JOIN  表2  ON  条件

我们在之前例子的基础上升级,给emp表添加一个新员工——小白龙,因为刚入职,所以他没有部门。

+----+-----------+--------+--------+------------+---------+
| id | name      | gender | salary | join_date  | dept_id |
+----+-----------+--------+--------+------------+---------+
|  1 | 孙悟空    | 男     |   7200 | 2013-02-24 |       1 |
|  2 | 猪八戒    | 男     |   3600 | 2012-07-04 |       2 |
|  3 | 唐僧      | 男     |   9000 | 2015-01-29 |       2 |
|  4 | 白骨精    | 女     |   3000 | 2010-04-20 |       3 |
|  5 | 蜘蛛精    | 女     |   6500 | 2016-07-25 |       1 |
|  6 | 小白龙    | 男     |   3000 | NULL       |    NULL |
+----+-----------+--------+--------+------------+---------+
6 rows in set (0.00 sec)

需求:查询所有员工信息,如果员工有所属部门,则查询部门的名称;没有部门则不显示部门的名称。

//使用内连接隐式查询,结果没有“小白龙”,不符合需求
mysql> SELECT-> t1.*,-> t2.`name`-> FROM-> emp t1,-> dept t2-> WHERE-> t1.`dept_id` = t2.`id`;
+----+-----------+--------+--------+------------+---------+-----------+
| id | name      | gender | salary | join_date  | dept_id | name      |
+----+-----------+--------+--------+------------+---------+-----------+
|  1 | 孙悟空    | 男     |   7200 | 2013-02-24 |       1 | 开发部    |
|  5 | 蜘蛛精    | 女     |   6500 | 2016-07-25 |       1 | 开发部    |
|  2 | 猪八戒    | 男     |   3600 | 2012-07-04 |       2 | 市场部    |
|  3 | 唐僧      | 男     |   9000 | 2015-01-29 |       2 | 市场部    |
|  4 | 白骨精    | 女     |   3000 | 2010-04-20 |       3 | 财务部    |
+----+-----------+--------+--------+------------+---------+-----------+
5 rows in set (0.01 sec)

使用内连接隐式查询,结果没有“小白龙”,不符合需求,因为小白龙的dept_id值是NULL,自然不会有匹配的id值。

接下来我们使用左外连接查询:

mysql> SELECT-> t1.*,-> t2.`name`-> FROM-> emp t1-> LEFT OUTER JOIN-> dept t2-> ON-> t1.`dept_id` = t2.`id`;
+----+-----------+--------+--------+------------+---------+-----------+
| id | name      | gender | salary | join_date  | dept_id | name      |
+----+-----------+--------+--------+------------+---------+-----------+
|  1 | 孙悟空    | 男     |   7200 | 2013-02-24 |       1 | 开发部    |
|  5 | 蜘蛛精    | 女     |   6500 | 2016-07-25 |       1 | 开发部    |
|  2 | 猪八戒    | 男     |   3600 | 2012-07-04 |       2 | 市场部    |
|  3 | 唐僧      | 男     |   9000 | 2015-01-29 |       2 | 市场部    |
|  4 | 白骨精    | 女     |   3000 | 2010-04-20 |       3 | 财务部    |
|  6 | 小白龙    | 男     |   3000 | NULL       |    NULL | NULL      |
+----+-----------+--------+--------+------------+---------+-----------+
6 rows in set (0.01 sec)

总结:左外连接查询的是左表所有数据以及其交集的部分。

  • 右外连接:语法– SELECT  字段列表  FROM  表1  RIGHT  [OUTER]  JOIN  表2  ON  条件

结论:右外连接查询的是右表所有数据以及其交集的部分。

mysql>  SELECT->  t1.*,->  t2.`name`-> FROM->  emp t1->  RIGHT OUTER JOIN-> dept t2-> ON-> t1.`dept_id` = t2.`id`;
+------+-----------+--------+--------+------------+---------+-----------+
| id   | name      | gender | salary | join_date  | dept_id | name      |
+------+-----------+--------+--------+------------+---------+-----------+
|    1 | 孙悟空    | 男     |   7200 | 2013-02-24 |       1 | 开发部    |
|    5 | 蜘蛛精    | 女     |   6500 | 2016-07-25 |       1 | 开发部    |
|    2 | 猪八戒    | 男     |   3600 | 2012-07-04 |       2 | 市场部    |
|    3 | 唐僧      | 男     |   9000 | 2015-01-29 |       2 | 市场部    |
|    4 | 白骨精    | 女     |   3000 | 2010-04-20 |       3 | 财务部    |
+------+-----------+--------+--------+------------+---------+-----------+
5 rows in set (0.00 sec)

“小白龙”消失了,因为“小白龙”既不是右表(dept)的内容,也不是两表的交集(不满足ON后面的条件),所以没有查询出来。

子查询

概念:子查询就是在查询中嵌套查询,称嵌套查询为子查询。

以上例继续,我们来查询最高工资的员工。

mysql> SELECT-> *-> FROM-> emp t1-> WHERE-> t1.`salary` = (-> SELECT-> MAX(salary)-> FROM-> emp-> );
+----+--------+--------+--------+------------+---------+
| id | name   | gender | salary | join_date  | dept_id |
+----+--------+--------+--------+------------+---------+
|  3 | 唐僧   | 男     |   9000 | 2015-01-29 |       2 |
+----+--------+--------+--------+------------+---------+
1 row in set (0.01 sec)

语句并不难理解,其实就是查询中嵌套查询,子查询的结果作为查询条件继续查询。

子查询的难点在于存在不同的情况,我们下面来依次介绍:

  • 子查询的结果是单行单列的:

该情况下,子查询可以作为一个条件,使用运算符去判断。

再看个示例,查看员工中工资小于平均工资的人:

mysql> SELECT-> *-> FROM-> emp t1-> WHERE-> t1.`salary` < (-> SELECT-> AVG(salary)-> FROM-> emp-> );
+----+-----------+--------+--------+------------+---------+
| id | name      | gender | salary | join_date  | dept_id |
+----+-----------+--------+--------+------------+---------+
|  2 | 猪八戒    | 男     |   3600 | 2012-07-04 |       2 |
|  4 | 白骨精    | 女     |   3000 | 2010-04-20 |       3 |
|  6 | 小白龙    | 男     |   3000 | NULL       |    NULL |
+----+-----------+--------+--------+------------+---------+
3 rows in set (0.00 sec)

注意,在子查询中,不能使用总查询中定义的别名。

  • 子查询的结果是多行单列的:

示例,查询“财务部”和“市场部”所有的员工信息

查询两个部门,就要先获得dept表中两个部门各自的id,然后在emp表中符合id1或者id2的员工,这样我们的子查询得到的会是一个单列多行的结果,我们要怎么应用呢?看示例:

SELECT  name,gender FROM emp   WHERE dept_id IN (
SELECT id FROM  dept  WHERE NAME='财务部' OR NAME='市场部' );name       gender
---------  --------
白骨精        女
猪八戒        男
唐僧         男
  • 子查询的结果是多行多列的:

该情况下,子查询不再可以作为WHERE后面的条件,而是可以作为一张虚拟表,再结合内连接查询等方法去查询。

示例:查询员工的入职日期是2013-11-11日之后的员工信息和部门信息。

SELECT * FROM
dept t1,(
SELECT * FROM emp
WHERE emp.`join_date` > '2013-11-11'
) t2  -- 多行多列的大于规定日期的员工表
WHERE t1.`id`=t2.`dept_id`;id  name           id  name       gender  salary  join_date   dept_id
------  ---------  ------  ---------  ------  ------  ----------  ---------2  市场部             3  唐僧         男         9000  2015-01-29          21  开发部             5  蜘蛛精        女         6500  2016-07-25          1

即先从原始员工表中筛选出一张“日期大于‘2013-11-11’”的员工表,然后该升级员工表与部门表进行隐式内连接查询即可。

其实这个我们使用内连接查询也可以实现:

SELECT * FROM
emp t1,
dept t2
WHERE t1.`dept_id` = t2.`id`
AND t1.`join_date` > '2013-11-11';id  name       gender  salary  join_date   dept_id      id  name
------  ---------  ------  ------  ----------  -------  ------  -----------3  唐僧         男         9000  2015-01-29        2       2  市场部  5  蜘蛛精        女         6500  2016-07-25        1       1  开发部  

已经写了不少内容了,我们把剩下的部分留给后面的文章

商业转载 请联系作者获得授权,非商业转载 请标明出处,谢谢

MySQL的基本学习(三)——DD/M/QL三类SQL语言和SQLyog相关推荐

  1. 语言翻译成汇编语言_学习编程有没有必要从C语言和C++学起?应该怎么学?

    硬件层级:这里也就是实体硬件,包括:CPU.内存.显卡等等...这些都不属于软件的范畴内. 汇编层级:在之前没有C/C++以及java之前,是汇编的年代.那么汇编语言对于我们来说,可读性是很查的,不适 ...

  2. sql语言和php,SQL语言快速入门(三)_php

    我们日常使用SQL语言的工作过程中,使用最多的还是从已经建立好的数据库中查询信息.下面,我们就来详细介绍一下如何使用SQL语言实现各种数据库查询操作. SELECT-FROM 为方便讲解,我们在数据库 ...

  3. 三、MySQL子查询学习笔记(标量子查询、列子查询、行子查询、表子查询 详解)

    三.MySQL子查询学习笔记 7:子查询 含义: 一条查询语句中又嵌套了另一条完整的select语句,其中被嵌套的select语句,称为子查询或内查询:在外面的查询语句,称为主查询或外查询 分类: 一 ...

  4. MYSQL高效基础学习系列1

    MYSQL高效基础学习系列1 目录 数据库基本概念 操作库,表和记录 数据类型 为字段指定的约束条件 目录 数据库基本概念 1.数据库服务器:运行数据库管理软件的计算机 2.数据库管理软件:mysql ...

  5. MySQL阶段性知识学习总结(一)

    目录 一.值得系统学习的文章 二.mysql批量造数据 三.mysql常用数据类型 日期和时间类型 整数型 小数类型 字符串类型 二进制类型 mysql数据类型的选择 1. 时间日期类型的选择 2. ...

  6. Docker学习三:Docker 数据管理

    前言 本次学习来自于datawhale组队学习: 教程地址为: https://github.com/datawhalechina/team-learning-program/tree/master/ ...

  7. 【笔记】MySQL的基础学习(二)

    [笔记]MySQL的基础学习(二) MySQL 老男孩  一 视图 视图其实就是给表起个别名 1.创建视图 格式:CREATE VIEW 视图名称 AS SQL语句 CREATE VIEW v1 AS ...

  8. mysql 临时表 事务_MySQL学习笔记十:游标/动态SQL/临时表/事务

    逆天十三少 发表于:2020-11-12 08:12 阅读: 90次 这篇教程主要讲解了MySQL学习笔记十:游标/动态SQL/临时表/事务,并附有相关的代码样列,我觉得非常有帮助,现在分享出来大家一 ...

  9. MYSQL优化汇总——学习入口

    mysql优化的方式总的有以下几种方式 1.msql服务器硬件的优化:单核CPU变成多核,加内存,这一般是运维干的事情. 2.mysql服务的配置参数的优化: 3.sql语句本身的优化: 4.数据库设 ...

  10. MySQL,Oracle系统学习,以及SQL语言-----数据库篇学习笔记

    Handouts MySQL和Oracle系统学习 一. 开篇立意(~~~~必看,有说明~~~~) 二. Oracle 篇 数据库存在之意义 基础概念(必须看,后面不会说明!!!) Oracle管理系 ...

最新文章

  1. 人工智能相关的几篇文章链接_20191008
  2. 神奇的10个人10个帽子的问题
  3. php手册常用的函数
  4. YUV视频格式到RGB32格式转换的速度优化 上篇(转)
  5. ubuntu 一个好系统
  6. 小心Redis漏洞让你服务器沦为肉鸡
  7. madagascar 软件安装方法
  8. JEP 277“增强弃用”非常好。 但这是一个更好的选择
  9. linux c mysql教程_linux下c操作mysql之增删改查
  10. 相约金陵丨7月9日,云和恩墨大讲堂 · 南京站邀您共论数字化转型实践
  11. YUM源安装,FTP安装
  12. tomcat 内存调整
  13. 引用了System.Configuration命名空间,却找不到ConfigurationManager类
  14. 泛型编程 与 STL
  15. 轻量级c语言开发环境,几款轻量级的C/C++编写软件
  16. 使用anaconda安装pytorch
  17. Euclid 欧几里得算法(c语言递归版)
  18. 中央台“互联网时代”纪录片分集要点
  19. 江苏省基础云计算机服务平台,江苏省一师一优课、一课一名师活动-江苏省基础教育云计算服务平台.doc...
  20. 《别用面包钓鲔鱼》--读书流水账no3

热门文章

  1. iOS UI切图@1x、@2x、@3x的实际尺寸
  2. 深度解析《ETC行业领军企业成谷科技》
  3. DNA分子结构3D模型
  4. 医用试管标签二维码方案研究
  5. 返回 代码: E_INVALIDARG (0x80070057)解决方法
  6. stm32 系统进入stop模式_STM32开发笔记78: 2种STOP模式的唤醒方法
  7. element-ui的select组件设置预选项没问题,但重新选中不改变的问题解决
  8. Pytorch学习率调整策略
  9. 2020计算机博弈大赛幻影围棋分组第二天 围棋规则学习
  10. 微信新功能,最牛的不是“斗图”!