最后
address varchar(100),
math int, english int
);
INSERT INTO student3(id,NAME,age,sex,address,math,english) VALUES (1,‘马云’,55,‘男’,‘杭州’,66,78),(2,‘马化腾’,45,‘女’,‘深圳’,98,87),(3,‘马景涛’,55,‘男’,‘香港’,56,77),(4,‘柳岩’,20,‘女’,‘湖南’,76,65),(5,‘柳青’,20,‘男’,‘湖南’,86,NULL),(6,‘刘德华’,57,‘男’,‘香港’,99,99),(7,‘马德’,22,‘女’,‘香港’,99,99),(8,‘德玛西亚’,18,‘男’,‘南京’,56,65);
3.5.1简单查询
查询表所有数据
1. 使用*表示所有列 SELECT * FROM 表名; 具体操作:
SELECT * FROM student3;
2. 写出查询每列的名称 SELECT 字段名1, 字段名2, 字段名3, … FROM 表名; 具体操作:
SELECT id, NAME ,age, sex, address, math, english FROM student3;
查询指定列
查询指定列的数据,多个列之间以逗号分隔 SELECT 字段名1, 字段名2… FROM 表名;
具体操作: 查询student3表中的id , name , age , sex , address 列
SELECT id, NAME ,age, sex, address FROM student3;
别名查询
1. 查询时给列、表指定别名需要使用AS关键字
2. 使用别名的好处是方便观看和处理查询到的数据 SELECT 字段名1 AS 别名, 字段名2 AS 别名… FROM 表名;
SELECT 字段名1 AS 别名, 字段名2 AS 别名… FROM 表名 AS 表别名;
注意:
查询给表取别名目前还看不到效果,需要到多表查询的时候才能体现出好处 AS关键字可以省略
3. 具体操作:查询sudent3表中name 和 age 列,name列的别名为”姓名”,age列的别名为”年龄”
SELECT NAME AS 姓名,age 年龄 FROM student3;
查询sudent3表中name和age列,student3表别名为s
SELECT NAME, age FROM student3 AS s;
查询给表取别名目前还看不到效果,需要到多表查询的时候才能体现出好处
清除重复值
为了演示重复值,我们再插入一条记录,
INSERT INTO student3 (id,NAME,age) VALUES(9,‘马云’,12);
1. 查询指定列并且结果不出现重复数据 SELECT DISTINCT 字段名 FROM 表名;
2. 具体操作:
查询name列并且结果不出现重复name
查询name,age列并且结果不出现重复name和age
SELECT DISTINCT NAME, age FROM student3;
测试完成之后 , 把刚刚插入的记录删除DELETE FROM student3 WHERE id = 9;
查询结果参与运算
1. 某列数据和固定值运算 SELECT 列名1 + 固定值 FROM 表名;
2. 某列数据和其他列数据参与运算 SELECT 列名1 + 列名2 FROM 表名;
注意: 参与运算的必须是数值类型
3. 具体例子:查询每个人的总成绩
SELECT NAME, math + english FROM student3;
结果确实将每条记录的math和english相加,有两个小问题
1.效果不好看
2.柳青的成绩为null我们来把这两个问题解决下
查询math + english的和使用别名”总成绩”
SELECT NAME, math + english 总成绩 FROM student3;
null值处理
注意 : null参与算术运算结果还是null.
ifnull(表达式1,表达式2) : 若表达式1的值为null,则返回表达式2的结果;若表达式1的值不为null,则返回表达式1的值因为english一列中有null值 , 我们可以使用ifnull解决 , 写法ifnull(english,0), 意思为若english值为null , 按0处理 ; 否则还是使用原来english的值.
SELECT NAME, math + IFNULL(english,0) 总成绩 FROM student3;
查询所有列与math + english的和并使用别名”总成绩”
SELECT *, math + IFNULL(english,0) 总成绩 FROM student3;
查询姓名、年龄,将每个人的年龄增加10岁
SELECT NAME, age + 10 FROM student3;
第四章 DQL语句
=========
4.1条件查询
4.1.1 比较运算符
>大于 <小于 <=小于等于 >=大于等于 =等于 <>、!=不等于
具体操作:查询math分数大于80分的学生
SELECT * FROM student3 WHERE math>80;
查询english分数小于或等于80分的学生
SELECT * FROM student3 WHERE english<=80;
查询age等于20岁的学生
SELECT * FROM student3 WHERE age=20;
查询age不等于20岁的学生
SELECT * FROM student3 WHERE age!=20;
SELECT * FROM student3 WHERE age<>20;
4.1.2 逻辑运算符
and(&&) 多个条件同时满足 or(||) 多个条件其中一个满足 not(!) 不满足
具体操作:查询age大于35且性别为男的学生(两个条件同时满足)
SELECT * FROM student3 WHERE age>35 AND sex=‘男’;
查询age大于35或性别为男的学生(两个条件其中一个满足)
SELECT * FROM student333 WHERE age>35 OR sex=‘男’;
查询id是1或3或5的学生
SELECT * FROM student3 WHERE id=1 OR id=3 OR id=5;
in关键字 语法格式:SELECT 字段名 FROM 表名 WHERE 字段 in (数据1, 数据2…); in里面的每个数据都会作为一次条件,只要满足条件的就会显示
具体操作:查询id是1或3或5的学生
SELECT * FROM student3 WHERE id IN (1,3,5);
查询id不是1或3或5的学生
SELECT * FROM student3 WHERE id NOT IN (1,3,5);
4.1.3 范围
BETWEEN 值1 AND 值2 表示从值1到值2范围,包头又包尾 比如:age BETWEEN 80 AND 100 相当于: age>=80 &&age<=100
具体操作:查询english成绩大于等于75,且小于等于90的学生
SELECT * FROM student3 WHERE english>=75 AND english<=90;
SELECT * FROM student3 WHERE english BETWEEN 75 AND 90;
4.1.4 like
LIKE表示模糊查询 SELECT * FROM 表名 WHERE 字段名 LIKE ‘通配符字符串’; 满足通配符字符串规则的数据就会显示出来 所谓的通配符字符串就是含有通配符的字符串 MySQL通配符有两个: %: 表示0个或多个字符(任意个字符) _: 表示一个字符
具体操作:查询姓马的学生
SELECT * FROM student3 WHERE NAME LIKE ‘马%’;
查询姓名中包含’德’字的学生
SELECT * FROM student3 WHERE NAME LIKE ‘%德%’;
查询姓马,且姓名有三个字的学生
SELECT * FROM student3 WHERE NAME LIKE ‘马__’;
4.2排序
通过ORDER BY子句,可以将查询出的结果进行排序(排序只是显示方式,不会影响数据库中数据的顺序) SELECT字段名 FROM 表名 WHERE 字段=值 ORDER BY 字段名 [ASC|DESC]; ASC: 升序, 默认是升序 DESC: 降序
4.2.1单列排序
单列排序就是使用一个字段排序
具体操作:查询所有数据,使用年龄降序排序
SELECT * FROM student3 ORDER BY age DESC;
4.2.2组合排序
组合排序就是先按第一个字段进行排序,如果第一个字段相同,才按第二个字段进行排序,依次类推。 上面的例子中,年龄是有相同的。当年龄相同再使用math进行排序 SELECT 字段名 FROM 表名 WHERE 字段=值 ORDER BY 字段名1 [ASC|DESC], 字段名2 [ASC|DESC];
具体操作:查询所有数据,在年龄降序排序的基础上,如果年龄相同再以数学成绩降序排序
SELECT * FROM student3 ORDER BY age DESC, math DESC;
4.3 聚合函数
之前我们做的查询都是横向查询,它们都是根据条件一行一行的进行判断,而使用聚合函数查询是纵向查询,它是对一列的值进行计算,然后返回一个结果值。另外聚合函数会忽略空值
五个聚合函数: count: 统计指定列记录数,记录为NULL的不统计 sum: 计算指定列的数值和,如果不是数值类型,那么计算结果为0 max: 计算指定列的最大值 min: 计算指定列的最小值 avg: 计算指定列的平均值,如果不是数值类型,那么计算结果为0
聚合函数的使用:写在 SQL语句SELECT后 字段名的地方 SELECT 字段名… FROM 表名; SELECT COUNT(age)FROM 表名;
具体操作:查询学生总数
SELECT COUNT(english) FROM student3;
我们发现对于NULL的记录不会统计
我们可以利用IFNULL()函数,如果记录为NULL,给个默认值,这样统计的数据就不会遗漏
ELECT COUNT(IFNULL(english,0)) FROM student3;
SELECT COUNT(*) FROM student3;
查询年龄大于40的总数
SELECT COUNT(*) FROM student3 WHERE age>40;
查询数学成绩总分
SELECT SUM(math) FROM student3;
查询数学成绩平均分
SELECT AVG(math) FROM student3;
查询数学成绩最高分
SELECT MAX(math) FROM student3;
查询数学成绩最低分
SELECT MIN(math) FROM student3;
4.4 分组
分组查询是指使用 GROUP BY语句对查询信息进行分组,相同数据作为一组 SELECT 字段1,字段2… FROM 表名GROUP BY 分组字段 [HAVING 条件];GROUP BY怎么分组的?将分组字段结果中相同内容作为一组 SELECT * FROM student3 GROUP BY sex;这句话会将sex相同的数据作为一组
GROUP BY将分组字段结果中相同内容作为一组,并且返回每组的第一条数据,所以单独分组没什么用处。分组的目的就是为了统计,一般分组会跟聚合函数一起使用。分组后聚合函数的作用?不是操作所有数据,而是操作一组数据。 SELECT SUM(math), sex FROM student3 GROUPBY sex; 效果如下:
实际上是将每组的math进行求和,返回每组统计的结果
注意事项:当我们使用某个字段分组,在查询的时候也需要将这个字段查询出来,否则看不到数据属于哪组的查询的时候没有查询出分组字段
查询的时候查询出分组字段
具体步骤:按性别分组
SELECT sex FROM student3 GROUP BY sex;
查询男女各多少人
1.查询所有数据,按性别分组。 2.统计每组人数SELECT sex, COUNT(*) FROM student3 GROUP BY sex;
查询年龄大于25岁的人,按性别分组,统计每组的人数
1.先过滤掉年龄小于25岁的人。2.再分组。3.最后统计每组的人数SELECT sex, COUNT(*) FROM student3 WHERE age > 25 GROUP BY sex;
查询年龄大于25岁的人,按性别分组,统计每组的人数,并只显示性别人数大于2的数据 有很多同学可能会将SQL语句写出这样:
SELECT sex, COUNT(*) FROM student3 WHERE age > 25 GROUP BY sex WHERE COUNT(*) >2;
注意: 并只显示性别人数>2的数据属于分组后的条件,对于分组后的条件需要使用having子句
SELECT sex, COUNT(*) FROM student3 WHERE age > 25 GROUP BY sex HAVING COUNT(*) >2;只有分组后人数大于2的`男`这组数据显示出来
having与where的区别
having是在分组后对数据进行过滤.
where是在分组前对数据进行过滤
having后面可以使用聚合函数
where后面不可以使用聚合函数
准备数据:
INSERT INTO student3(id,NAME,age,sex,address,math,english) VALUES (9,‘唐僧’,25,‘男’,‘长安’,87,78),(10,‘孙悟空’,18,‘男’,‘花果山’,100,66),(11,‘猪八戒’,22,‘男’,‘高老庄’,58,78),(12,‘沙僧’,50,‘男’,‘流沙河’,77,88),(13,‘白骨精’,22,‘女’,‘白虎岭’,66,66),(14,‘蜘蛛精’,23,‘女’,‘盘丝洞’,88,88);
4.5 limit语句
LIMIT是限制的意思,所以LIMIT的作用就是限制查询记录的条数。 SELECT *|字段列表 [as 别名] FROM 表名[WHERE子句] [GROUP BY子句][HAVING子句][ORDER BY子句][LIMIT子句]; 思考:limit子句为什么排在最后? 因为前面所有的限制条件都处理完了,只剩下显示多少条记录的问题了!
LIMIT语法格式: LIMIT offset,length; 或者limit length; offset是指偏移量,可以认为是跳过的记录数量,默认为0 length是指需要显示的总记录数
具体步骤:查询学生表中数据,从第三条开始显示,显示6条
我们可以认为跳过前面2条,取6条数据
SELECT * FROM student3 LIMIT 2,6;
LIMIT的使用场景:分页 比如我们登录京东,淘宝,返回的商品信息可能有几万条,不是一次全部显示出来。是一页显示固定的条数。 假设我们一每页显示5条记录的方式来分页,SQL语句如下:
‐ 每页显示5条
‐‐ 第一页: LIMIT 0,5; 跳过0条,显示5条
‐‐ 第二页: LIMIT 5,5; 跳过5条,显示5条
‐‐ 第三页: LIMIT 10,5; 跳过10条,显示5条
SELECT * FROM student3 LIMIT 0,5;SELECT * FROM student3 LIMIT 5,5;SELECT * FROM student3 LIMIT 10,5;
注意:
如果第一个参数是0可以简写:
SELECT * FROM student3 LIMIT 0,5;
SELECT * FROM student3 LIMIT 5;
LIMIT 10,5; – 不够5条,有多少显示多少
第五章 数据库备份
=========
5.1 备份应用场景
在服务器进行数据传输、数据存储和数据交换,就有可能产生数据故障。比如发生意外停机或存储介质损坏。这时,如果没有采取数据备份和数据恢复手段与措施,就会导致数据的丢失,造成的损失是无法弥补与估量的。
5.2 source命令备份与还原
备份格式: mysqldump -u用户名 -p密码 数据库 > 文件的路径
还原格式: SOURCE 导入文件的路径;
注意:还原的时候需要先登录MySQL,并选中对应的数据库
具体操作:备份day22数据库中的数据
mysqldump ‐uroot ‐proot day22 > C:\work\课改\MYSQL课改资料\Day02‐MYSQL多表查询\code\bak.sql
数据库中的所有表和数据都会导出成SQL语句
还原day22数据库中的数据
删除day22数据库中的所有表
登录MySQL
mysql ‐uroot ‐proot
选中数据库
use day22;
select database();
使用SOURCE命令还原数据
source C:\work\课改\MYSQL课改资料\Day02‐MYSQL多表查询\code\bak.sql
5.3 图形化界面备份与还原
备份day22数据库中的数据
包含创建数据库的语句
还原day22数据库中的数据
删除day22数据库
数据库列表区域右键“执行SQL脚本”, 指定要执行的SQL文件,执行即可
第六章 数据库约束
=========
对表中的数据进行进一步的限制,保证数据的正确性、有效性和完整性。 约束种类:
PRIMARY KEY: 主键
UNIQUE: 唯一
NOT NULL: 非空
DEFAULT: 默认
FOREIGN KEY: 外键
6.1 主键
6.1.1 主键作用
用来唯一标识一条记录,每个表都应该有一个主键,并且每个表只能有一个主键。 有些记录的 name,age,score 字段的值都一样时,那么就没法区分这些数据,造成数据库的记录不唯一,这样就不方便管理数据
哪个字段应该作为表的主键? 通常不用业务字段作为主键,单独给每张表设计一个id的字段,把id作为主键。主键是给数据库和程序使用的,不是给最终的客户使用的。所以主键有没有含义没有关系,只要不重复,非空就行。
6.1.2 创建主键
主键:PRIMARY KEY 主键的特点:
主键必须包含唯一的值
主键列不能包含NULL值
创建主键方式:
1. 在创建表的时候给字段添加主键
字段名 字段类型 PRIMARY KEY
2. 在已有表中添加主键 ALTER TABLE 表名 ADD PRIMARY KEY(字段名);
具体操作:创建表学生表st5, 包含字段(id, name, age)将id做为主键
CREATE TABLE st5 (
id INT PRIMARY KEY, ‐‐ id是主键 NAME VARCHAR(20),
age INT
);
添加数据
INSERT INTO st5 (id, NAME) VALUES (1, ‘唐伯虎’);
INSERT INTO st5 (id, NAME) VALUES (2, ‘周文宾’);
INSERT INTO st5 (id, NAME) VALUES (3, ‘祝枝山’);
INSERT INTO st5 (id, NAME) VALUES (4, ‘文征明’);
插入重复的主键值
主键是唯一的不能重复:
Duplicate entry ‘1’ for key 'PRIMARY’INSERT INTO st5 (id, NAME) VALUES (1, ‘文征明2’);
插入NULL的主键值
主键是不能为空的:
Column ‘id’ cannot be nullINSERT INTO st5 (id, NAME) VALUES (NULL, ‘文征明3’)
注意 : 一张表中只有一个主键 , 主键可以为多个字段 , 不过我们一般增减一个字段 id 来作为主键.
6.1.3 删除主键
ALTER TABLE 表名 DROP PRIMARY KEY;
具体操作:删除st5表的主键
ALTER TABLE st5 DROP PRIMARY KEY;
6.1.4 主键自增
主键如果让我们自己添加很有可能重复,我们通常希望在每次插入新记录时,数据库自动生成主键字段的值AUTO_INCREMENT 表示自动增长(字段类型是整型数字)
具体操作:创建学生表st6, 包含字段(id, name, age)将id做为主键并自动增长
CREATE TABLE st6 (
id INT PRIMARY KEY AUTO_INCREMENT,
NAME VARCHAR(20),
age INT
);
插入数据
主键默认从1开始自动增长
INSERT INTO st6 (NAME, age) VALUES (‘唐僧’, 22);
INSERT INTO st6 (NAME, age) VALUES (‘孙悟空’, 26);
INSERT INTO st6 (NAME, age) VALUES (‘猪八戒’, 25);
INSERT INTO st6 (NAME, age) VALUES (‘沙僧’, 20);
DELETE和TRUNCATE的区别
DELETE 删除表中的数据,但不重置AUTO_INCREMENT的值。
TRUNCATE 摧毁表,重建表,AUTO_INCREMENT重置为1
6.2 唯一
在这张表中这个字段的值不能重复
6.2.1唯一约束
字段名 字段类型 UNIQUE
6.2.2 实现唯一约束
具体步骤:创建学生表st7, 包含字段(id, name),name这一列设置唯一约束,不能出现同名的学生
CREATE TABLE st7 (
id INT,
NAME VARCHAR(20) UNIQUE
);
添加一个学生
INSERT INTO st7 VALUES (1, ‘貂蝉’);
INSERT INTO st7 VALUES (2, ‘西施’);
INSERT INTO st7 VALUES (3, ‘王昭君’);
INSERT INTO st7 VALUES (4, ‘杨玉环’);
‐‐ 插入相同的名字出现name重复: Duplicate entry ‘貂蝉’ for key ‘name’
INSERT INTO st7 VALUES (5, ‘貂蝉’); ‐‐ 出现多个null的时候会怎样?因为null是没有值,所以不存在重复的问题
INSERT INTO st3 VALUES (5, NULL);INSERT INTO st3 VALUES (6, NULL);
6.3 非空
这个字段必须设置值,不能是NULL
6.3.1 非空约束的基本语法格式
字段名 字段类型 NOT NULL
具体操作:创建表学生表st8, 包含字段(id,name,gender)其中name不能为NULL
CREATE TABLE st8 (
id INT,
NAME VARCHAR(20) NOT NULL, gender CHAR(2)
);
添加一条完整的记录
INSERT INTO st8 VALUES (1, ‘郭富城’, ‘男’);
INSERT INTO st8 VALUES (2, ‘黎明’, ‘男’);
INSERT INTO st8 VALUES (3, ‘张学友’, ‘男’);
INSERT INTO st8 VALUES (4, ‘刘德华’, ‘男’);
‐‐ 姓名不赋值出现姓名不能为null: Column ‘name’ cannot be null
INSERT INTO st8 VALUES (5, NULL, ‘男’);
6.3.2 默认值
往表中添加数据时,如果不指定这个字段的数据,就使用默认值默认值格式 字段名 字段类型 DEFAULT 默认值
具体步骤:创建一个学生表 st9,包含字段(id,name,address), 地址默认值是广州
CREATE TABLE st9 (
id INT,
NAME VARCHAR(20), address VARCHAR(50) DEFAULT ‘广州’
)
添加一条记录,使用默认地址
INSERT INTO st9 (id, NAME) VALUES (1, ‘刘德华’);
添加一条记录,不使用默认地址
INSERT INTO st9 VALUES (2, ‘张学友’, ‘香港’);
第七章 表关系
=======
7.1 表关系概念图
现实生活中,实体与实体之间肯定是有关系的,比如:老公和老婆,部门和员工,老师和学生等。那么我们在设计表的时候,就应该体现出表与表之间的这种关系!分成三种:
1. 一对一
2. 一对多
3. 多对多
7.2 一对多
对多(1:n) 例如:班级和学生,部门和员工,客户和订单,分类和商品 一对多建表原则: 在从表(多方)创建一个字段,指向主表(一方)的主键.我们把这个字段称之为外键.
7.3 多对多
多对多(m:n) 例如:老师和学生,学生和课程,用户和角色 多对多关系建表原则: 需要创建第三张表,中间表中至少两个字段,这两个字段分别作为外键指向各自一方的主键。
7.4 一对(了解)
对一(1:1) 在实际的开发中应用不多.因为一对一可以创建成一张表。 两种建表原则:
外键唯一:主表的主键和从表的外键(唯一),形成主外键关系,
外键唯一UNIQUE外键是主键:主表的主键和从表的主键,形成主外键关系
7.5 外键约束
7.5.1 什么是外键约束
一张表中的某个字段引用另一个表的主键 主表: 约束别人 副表/从表: 使用别人的数据,被别人约束
7.5.2 创建外键
1. 新建表时增加外键: [CONSTRAINT] [外键约束名称] FOREIGN KEY(外键字段名) REFERENCES 主表名(主键字段名)
关键字解释:
CONSTRAINT – 约束关键字
FOREIGN KEY(外键字段名) –- 某个字段作为外键
REFERENCES – 主表名(主键字段名) 表示参照主表中的某个字段
2.已有表增加外键: ALTER TABLE 从表 ADD [CONSTRAINT] [外键约束名称] FOREIGN KEY (外键字段名) REFERENCES 主表(主键字段名);
具体操作:以"新建表时添加外键"演示
‐ 先创建部门表
CREATE TABLE department (
id INT PRIMARY KEY AUTO_INCREMENT,
dep_name VARCHAR(20),
dep_location VARCHAR(20)
);
‐‐ 添加2个部门
INSERT INTO department (dep_name, dep_location) VALUES (‘研发部’, ‘广州’), (‘销售部’, ‘深圳’);
‐‐ 然后创建员工表,添加外键约束
CREATE TABLE employee (
id INT PRIMARY KEY AUTO_INCREMENT,
NAME VARCHAR(20),
age INT, dep_id INT,
‐‐ 添加一个外键 ‐‐ 外键取名公司要求,一般fk结尾 CONSTRAINT emp_depid_ref_dep_id_fk FOREIGN KEY(dep_id) REFERENCES department(id)
);
正常添加数据
INSERT INTO employee (NAME, age, dep_id) VALUES(‘张三’, 20, 1),(‘李四’, 21, 1),(‘王五’, 20, 1),(‘老王’, 20, 2),(‘大王’, 22, 2),(‘小王’, 18, 2);
部门错误的数据添加失败
INSERT INTO employee (NAME, age, dep_id) VALUES (‘二王’, 20, 5);
7.5.3 删除外键(了解)
ALTER TABLE 从表 drop foreign key 外键名称;
具体操作:删除employee表的emp_depid_ref_dep_id_fk外键
ALTER TABLE employee DROP FOREIGN KEY emp_depid_ref_dep_id_fk;
在employee表情存在况下添加外键
ALTER TABLE employee ADD CONSTRAINT emp_depid_ref_dep_id_fk FOREIGN KEY(dep_id) REFERENCES department(id);
第八章 三范式
=======
8.1 什么是范式
范式是指:设计数据库表的规则(Normal Form) 好的数据库设计对数据的存储性能和后期的程序开发,都会产生重要的影响。建立科学的,规范的数据库就需要满足一些规则来优化数据的设计和存储
8.2 范式的基本分类
目前关系数据库有六种范式:第一范式(1NF)、第二范式(2NF)、第三范式(3NF)、巴斯-科德范式(BCNF)、第四范式(4NF)和第五范式(5NF,又称完美范式)。满足最低要求的范式是第一范式(1NF)。在第一范式的基础上进一步满足更多规范要求的称为第二范式(2NF),其余范式以次类推。一般说来,数据库只需满足第三范式(3NF)就行了。
8.3 第一范式
即数据库表的每一列都是不可分割的原子数据项,而不能是集合、数组、记录等非原子数据项。即实体中的某个属性有多个值时,必须拆分为不同的属性。在符合第一范式(1NF)表中每个列的值只能是表的一个属性或一个属性的一部分。简而言之,第一范式每一列不可再拆分,称为原子性。 第一范式:每一列不能再拆分
总结:如果不遵守第一范式,查询出数据还需要进一步处理(查询不方便)。遵守第一范式,需要什么字段的数据就查询什么数据(方便查询)。
8.4 第二范式
第二范式(2NF)要求数据库表中的每个实例或记录必须可以被唯一地区分。选取一个能区分每个实体的属性或属性组,作为实体的唯一标识。例如在员工表中的身份证号码即可实现每个员工的区分,该身份证号码即为候选键,任何一个候选键都可以被选作主键。在找不到候选键时,可额外增加属性以实现区分。 第二范式(2NF)要求实体的属性完全依赖于主关键字。所谓完全依赖是指不能存在仅依赖主关键字一部分的属性。如果存在,那么这个属性和主关键字的这一部分应该分离出来形成一个新的实体,新实体与原实体之间是一对多的关系。为实现区分通常需要为表加上一个列,以存储各个实例的唯一标识。简而言之,第二范式就是在第一范式的基础上属性完全依赖于主键。
第二范式:1. 一张表只描述一件事情
2. 表中的每一个字段都依赖于主键
总结:如果不准守第二范式,数据冗余,相同数据无法区分。遵守第二范式减少数据冗余,通过主键区分相同数据。
8.5 第三范式
在2NF基础上,任何非主属性不依赖于其它非主属性(在2NF基础上消除传递依赖) 第三范式(3NF)是第二范式(2NF)的一个子集,即满足第三范式(3NF)必须满足第二范式(2NF)。简而言之,第三范式(3NF)要求一个关系中不包含已在其它关系已包含的非主关键字信息。
总结:如果不准守第三范式,可能会有相同数据无法区分,修改数据的时候多张表都需要修改(不方便修改)。遵守第三范式通过id可以区分相同数据,修改数据的时候只需要修改一张表(方便修改)。
第九章 多表查询
========
9.1 什么是多表查询
同时查询多张表获取到需要的数据 比如:我们想查询到开发部有多少人,需要将部门表和员工表同时进行查询
准备数据
创建部门表
CREATE TABLE dept (
id INT PRIMARY KEY AUTO_INCREMENT,
NAME VARCHAR(20)
);
INSERT INTO dept (NAME) VALUES (‘开发部’),(‘市场部’),(‘财务部’);
‐‐ 创建员工表
CREATE TABLE emp (
id INT PRIMARY KEY AUTO_INCREMENT,
NAME VARCHAR(10),
gender CHAR(1),
‐‐ 性别 salary DOUBLE,
‐‐ 工资 join_date DATE
, ‐‐ 入职日期 dept_id INT
);
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,‘2010‐12‐02’,2);
INSERT INTO emp(NAME,gender,salary,join_date,dept_id) VALUES(‘唐僧’,‘男’,9000,‘2008‐08‐08’,2);
INSERT INTO emp(NAME,gender,salary,join_date,dept_id) VALUES(‘白骨精’,‘女’,5000,‘2015‐10‐07’,3);
INSERT INTO emp(NAME,gender,salary,join_date,dept_id) VALUES(‘蜘蛛精’,‘女’,4500,‘2011‐03‐14’,1);
9.2 笛尔卡乘积现象
9.2.1 什么是笛尔卡乘积现象
多表查询时左表的每条数据和右表的每条数据组合,这种效果成为笛卡尔积需求:查询每个部门有哪些人具体操作:
SELECT * FROM dept, emp;
以上数据其实是左表的每条数据和右表的每条数据组合。左表有3条,右表有5条,最终组合后3*5=15条数据。
9.2.2 如何清除笛尔卡乘积现象
我们发现不是所有的数据组合都是有用的,只有员工表.dept_id = 部门表.id 的数据才是有用的。所以需要通过条件过滤掉没用的数据。
SELECT * FROM dept, emp WHERE emp.`dept_id`=dept.`id`;
9.3 内连接
用左边表的记录去匹配右边表的记录,如果符合条件的则显示
9.3.1 隐式内连接
隐式内连接:看不到JOIN关键字,条件使用WHERE指定 SELECT 字段名 FROM 左表, 右表 WHERE 条件;
9.3.2 显示内连接
显示内连接:使用INNER JOIN … ON语句, 可以省略INNER SELECT 字段名 FROM 左表 INNER JOIN 右表 ON 条件;
具体操作:查询唐僧的信息,显示员工id,姓名,性别,工资和所在的部门名称,我们发现需要联合2张表同时才能查询出需要的数据,我们使用内连接
最后
面试前一定少不了刷题,为了方便大家复习,我分享一波个人整理的面试大全宝典
- Java核心知识整理
Java核心知识
- Spring全家桶(实战系列)
- 其他电子书资料
Step3:刷题
既然是要面试,那么就少不了刷题,实际上春节回家后,哪儿也去不了,我自己是刷了不少面试题的,所以在面试过程中才能够做到心中有数,基本上会清楚面试过程中会问到哪些知识点,高频题又有哪些,所以刷题是面试前期准备过程中非常重要的一点。
以下是我私藏的面试题库:
size_20,color_FFFFFF,t_70,g_se,x_16)
以上数据其实是左表的每条数据和右表的每条数据组合。左表有3条,右表有5条,最终组合后3*5=15条数据。
9.2.2 如何清除笛尔卡乘积现象
我们发现不是所有的数据组合都是有用的,只有员工表.dept_id = 部门表.id 的数据才是有用的。所以需要通过条件过滤掉没用的数据。
SELECT * FROM dept, emp WHERE emp.`dept_id`=dept.`id`;
9.3 内连接
用左边表的记录去匹配右边表的记录,如果符合条件的则显示
9.3.1 隐式内连接
隐式内连接:看不到JOIN关键字,条件使用WHERE指定 SELECT 字段名 FROM 左表, 右表 WHERE 条件;
9.3.2 显示内连接
显示内连接:使用INNER JOIN … ON语句, 可以省略INNER SELECT 字段名 FROM 左表 INNER JOIN 右表 ON 条件;
具体操作:查询唐僧的信息,显示员工id,姓名,性别,工资和所在的部门名称,我们发现需要联合2张表同时才能查询出需要的数据,我们使用内连接
最后
面试前一定少不了刷题,为了方便大家复习,我分享一波个人整理的面试大全宝典
- Java核心知识整理
[外链图片转存中…(img-t0v0RRlz-1715106281717)]
Java核心知识
- Spring全家桶(实战系列)
[外链图片转存中…(img-zYw4Zhtm-1715106281719)]
- 其他电子书资料
[外链图片转存中…(img-DT61VPlD-1715106281720)]
Step3:刷题
既然是要面试,那么就少不了刷题,实际上春节回家后,哪儿也去不了,我自己是刷了不少面试题的,所以在面试过程中才能够做到心中有数,基本上会清楚面试过程中会问到哪些知识点,高频题又有哪些,所以刷题是面试前期准备过程中非常重要的一点。
以下是我私藏的面试题库:
[外链图片转存中…(img-cDbXM9qJ-1715106281720)]