<>一、表与表之间的关系
1.1 简介
1.mysql 是关系型数据库:表与表之间存在的关系
2.常见的表与表之间的关系:一对一 一对多 多对多
1.2 一对一的关系
代码
#创建丈夫表 CREATE TABLE man( `mid` INT(11) PRIMARY KEY AUTO_INCREMENT, mname
VARCHAR(20) ); #创建妻子表 CREATE TABLE woman( wid INT(11) PRIMARY KEY AUTO_INCREMENT
, wname VARCHAR(20), `mid` INT(11) ); #语法: ALTER TABLE 从表 ADD CONSTRAINT 外键名称
FOREIGN KEY(外键列名) REFERENCES 主表(主键) #添加外键关键 ALTER TABLE woman ADD CONSTRAINT
fk_midFOREIGN KEY(`mid`) REFERENCES man(`mid`)
效果
1.3 一对多的关系
代码
#创建部门表 CREATE TABLE dept( did INT(11) PRIMARY KEY AUTO_INCREMENT, dname VARCHAR
(20) ); #创建员工表 CREATE TABLE emp( eid INT(11) PRIMARY KEY AUTO_INCREMENT, ename
VARCHAR(20), did INT(11) ); #添加外键关联 ALTER TABLE emp ADD CONSTRAINT fk_eid
FOREIGN KEY(did) REFERENCES dept(did)
注意点
A.外键是设置在从表中(多) 一般从表的外键对应主表的主键
B.外键的数据类型以及长度 必须与主表的数据类型以及长度一致
C.增加数据的时候 需要先增加主表 再增加从表
D.删除数据的时候 先删除从表 再删除主表
删除外键
A.先删除外键
语法: alter table 从表表名 drop FOREIGN KEY 外键名称
ALTER TABLE emp DROP FOREIGN KEY fk_eid
B.删除外键的索引
效果
1.4 多对多的关系
step01 生活中多对多关系
1.生活中 多对多的关系: 多个演员==>多个角色 学生==>成绩
step02 设置表
代码
#创建演员表 CREATE TABLE actor( aid INT(11) PRIMARY KEY AUTO_INCREMENT, aname
VARCHAR(20) ); #创建角色表 CREATE TABLE role( rid INT(11) PRIMARY KEY AUTO_INCREMENT,
rnameVARCHAR(20) ); #创建一张中间表 CREATE TABLE a_r( a_r_id INT(11)PRIMARY KEY
AUTO_INCREMENT, aid INT(11), rid INT(11) ); #添加外键关联 ALTER TABLE a_r ADD
CONSTRAINT fk_aid FOREIGN KEY(aid) REFERENCES actor(aid) ALTER TABLE a_r ADD
CONSTRAINT fk_rid FOREIGN KEY(rid) REFERENCES role(rid)
效果
<>二、三大范式
1.三大范式也是用于来约束数据库 保证数据的完整性 以及正确性
2.三大范式的特点:
A.第一大范式: 表中的每一列是最小的原子单位 不能进行再拆分
B.第二大范式: 每一张表 只能描述一种事物
C.第三大范式: 在遵循前两大范式的基础上 不能出现局部依赖 只能与主键建立依赖关系
第一大范式
第二大范式
第三范式
<>三、多表查询
3.1 素材
#创建部门表 CREATE TABLE dept( did INT(11) PRIMARY KEY AUTO_INCREMENT, dname VARCHAR
(20), des VARCHAR(30) ); INSERT INTO dept(dname,des)VALUES("研发部门","撸代码"),("行政部门"
,"养花") ,("人事部","招人") #创建一张员工表 CREATE TABLE emp( eid INT(11) PRIMARY KEY
AUTO_INCREMENT, ename VARCHAR(20), esal DOUBLE, edesc VARCHAR(20) ); INSERT INTO
emp(ename,esal,edesc)VALUES("小明",2000,"哈哈") ,("小王",3000,"呵呵"),("小啊",4000,"kk"),
("dd",5000,"ndn"), ("222",6000,"afdaf"),("yy",9000,"asdfadsf")
3.2 表结构
3.3 非等值查询
1.语法: select * from 表1,表2
2.案例:
#查询员工的信息 以及部门的信息
SELECT d.,e. FROM dept d,emp e
2.问题:
出现大量的错误的数据 这个显示是笛卡尔现象 笛卡尔乘积 3*6 =18
图片数据有差别
结果
3.4 连接查询
<>3.4.1 显示内连接(inner join 表名 on 关联条件)
1.概念:使用mysql中inner join关键字来进行连接查询 就是显示内连接
2.语法:select * from 左表 inner join 右表 on 关联的条件
3.案例:
#查询所有员工以及对应的部门的信息
SELECT d.,e. FROM dept d INNER JOIN emp e ON d.did=e.did
取值范围
<>3.4.2 隐式内连接(from表名,表名 where 关联条件)
1.概念:不使用inner join关键字来进行连接查询 就是隐式内连接
2.语法: select * from 左表, 右表 where 关联条件
3.案例:
#查询所有员工以及对应的部门的信息
SELECT d.,e. FROM dept d,emp e WHERE d.did=e.did
<>3.5 左外连接(left join 右表 on 关联条件)
1.语法:select * from 左表 left join 右表 on 匹配条件
2.匹配的规则:以左表为基准 右表一一进行匹配 如果可以匹配 则两表正常显示 如果不可以匹配
左表依然显示 右表设置为null
3.案例:
不管部门下是否有员工 都需要查询出部门的信息
SELECT d.,e. FROM dept d LEFT JOIN emp e ON d.did=e.did
取值部分
<>3.6 右外连接(right join 右表 on 关联条件)
1.语法:select * from 左表 right join 右表 on 匹配条件
2.匹配规则:
以右为基准 左表一一进行匹配 如果可以匹配 则两表正常显示 如果不可以匹配
右表依然显示 左表设置为null
3.查询所有的员工的信息 不管是否有对应的部门
SELECT d.,e. FROM dept d RIGHT JOIN emp e ON d.did=e.did
取值部分
<>3.7 子查询
1.概念:一个查询语句嵌套另一个完成的查询语句
2.两种体现:A.一个子查询的结果当做另一查询语句条件使用 B.一个查询语句的结果当前另一个查询语
句的列来使用
3.第一种体现:
A.查询研发部门下所有的员工
B.分析: a.查询所有的员工 b.查询出部门是研发部门 c.关联条件 did
C. select * from emp select * from dept where dname=“研发部门”
D.SELECT * FROM emp e WHERE e.did
IN(SELECT d.did FROM dept d WHERE d.dname=“研发部门” )
4.第二种体现
A.查询出所有员工的信息 以及部门的名称
B.分析: 查询所有员工的信息 b.查询出部门的名称 c.关联条件 did
C.SELECT e.*,(SELECT d.dname FROM dept d WHERE d.did=e.did) AS dname FROM
emp e
<>四、多表查询的练习
4.1 备份与还原
4.1.1 第一种 使用dos窗口来进行备份与还原
备份
指令:mysqldump -u用户名 -p密码 数据库的库名 > 地址
还原
注意点 数据库必须存在
指令:mysql -u用户名 -p密码 数据库的库名 < 地址
4.2 第二种 使用可视化工具
备份
还原
4.3 多表查询
#查询参加了考试的同学信息(学号、学生姓名、科目编号、分数) #学号、学生姓名 学生表 科目编号、分数 分数 SELECT s.StudentNo,s.
StudentName,r.SubjectNo,r.StudentResult FROM student s INNER JOIN result r ON s.
StudentNo= r.StudentNo #查询出了所有同学,不考试的也查出来 SELECT s.StudentNo,s.StudentName,r.
SubjectNo,r.StudentResult FROM student s LEFT JOIN result r ON s.StudentNo = r.
StudentNo#查一下缺考的同学 SELECT s.StudentNo,s.StudentName,r.SubjectNo,r.StudentResult
FROM student s LEFT JOIN result r ON s.StudentNo = r.StudentNo WHERE r.
StudentResultIS NULL #思考题:查询参加了考试的同学信息(学号、学生姓名、科目名、分数) #学号、学生姓名 学生表 #科目名 科目表 #分数
SELECT s.StudentNo,s.StudentName,sub.subjectName,r.StudentResult FROM student s
INNER JOIN result r ON s.StudentNo = r.StudentNo INNER JOIN `subject` sub ON r.
SubjectNo= sub.SubjectNo # 查询《数据库结构-1》的所有考试结果,并按成绩由高到低排列 SELECT s.StudentNo,s.
StudentName,sub.subjectName,r.StudentResult FROM student s INNER JOIN result r
ON s.StudentNo = r.StudentNo INNER JOIN `subject` sub ON r.SubjectNo = sub.
SubjectNoWHERE sub.subjectName="数据库结构-1" ORDER BY r.StudentResult DESC
#查询课程为《高等数学-2》且分数不小于80分的学生的学号和姓名 SELECT s.StudentNo,s.StudentName FROM student s
INNER JOIN result r ON s.StudentNo =r.StudentNo INNER JOIN `subject` sub ON r.
SubjectNo= sub.SubjectNo WHERE r.StudentResult >=80 AND sub.subjectName="高等数学-2"
#查询课程为《高等数学-2》且分数不小于80分的学生的学号和姓名 SELECT r.StudentNo FROM result r WHERE r.
StudentResult>=80 AND r.SubjectNo SELECT sub.subjectNo FROM `subject` sub WHERE
sub.subjectName="高等数学-2" SELECT s.StudentNo,s.StudentName FROM student s WHERE s
.StudentNo IN (SELECT r.StudentNo FROM result r WHERE r.StudentResult >=80 AND r
.SubjectNo IN(SELECT sub.subjectNo FROM `subject` sub WHERE sub.subjectName=
"高等数 学-2")) #案例 :查询《C-语言1》的前5名学生成绩信息 SELECT s.StudentNo,s.StudentName,r.
StudentResultFROM student s INNER JOIN result r ON s.StudentNo = r.StudentNo
INNER JOIN `subject` sub ON r.SubjectNo = sub.subjectNo WHERE sub.subjectName=
"C语言-1" ORDER BY r.StudentResult DESC LIMIT 0,5
#查询课程为《JAVA第一学年》成绩前10名分数大于80的学生信息(学号,姓名,分数) #使用连接查询与子查询 SELECT s.StudentNo,s.
StudentName,r.StudentResult FROM student s INNER JOIN result r ON s.StudentNo =r
.StudentNo WHERE r.StudentResult >80 AND r.SubjectNo IN(SELECT sub.SubjectNo
FROM `subject` sub WHERE sub.subjectName="JAVA第一学年" ) ORDER BY r.StudentResult
DESC LIMIT 0,10 #按照不同的课程,分别算出其平均分、最高分和最低分, #对于低于60分平均分的不予显示 SELECT sub.
subjectName,ROUND(AVG(r.StudentResult),2) AS "平均分", MAX(r.StudentResult) AS
"最高分",MIN(r.StudentResult) AS "最低分" FROM `subject` sub INNER JOIN result r ON
sub.subjectNo=r.SubjectNo GROUP BY sub.subjectNo HAVING AVG(r.StudentResult) >=
60
总结
<>SQL语句分类
1.DDL 数据库定义语言 主要是用于来操作数据库 以及数据库表 关键字 alter drop create truncate
2. DQL 数据库查询语言 主要是用于操作数据库表 主要用于查询数据库中的数据 关键字 select
3. DML 数据库操纵语言 主要是用于操作数据库中数据表 主要是对数据进行 增加 insert 删除 delete 修改 update
4. DCL 数据库控制语言 主要是用于对数据库的用户的管理 以及权限的管理 运维工程师操作 关键字为grant、revoke**
<>单表查询
增删改
intsert into 表名(列名,列名..)values(对应列名的数据,对应列名的数据..) delete from 表名 where 条件 例(id=
1) #删除多行 delete from 表名 where id in (a,b,c) update 表名 set 列名=值,列名=值 where 条件
查
select 列名 from 表名 where 条件
模糊查询
1.模糊查询的关键字 like
2.匹配的符号 % 匹配多个 _ 匹配一个
#查询第二个字为'想'的所有商品 SELECT * FROM product WHERE pname LIKE '_想%'
order by 升序 asc 降序 desc
查询第一条与第二条数据
SELECT * FROM product LIMIT 0,2 //第一页 每页显示两条数据
去重
SELECT DISTINCT price FROM product
分组
SELECT category_name ,COUNT(1) FROM product GROUP BY category_name
HAVING category_name IS NOT NULL
聚合函数count()
COUNT(列名) 会统计 不包括null值的所有符合条件的字段的条数
COUNT( * )会统计 包括null值的所有符合条件的字段的条数
count(1)会统计 包括null值的所有符合条件的字段的条数
count(1) 的查询速度比COUNT( * )快
<>多表查询
select * from 表名 where 条件
直接英翻中 选择筛选 列名,列名… 从 表名,表名… 当 什么条件时
列名…就是显示的结果表的列名
表名 就是从哪张表中查询 ,如果表中没有相应列名就会报错,结果表显示不出来,子查询无连接表的功能
用where 时,表名… 中的多张表会连接起来,只要多张表有的列名都可以在结果表显示出来,不报错
连接表功能的语句还有 INNER JION 内连接
左连接 LEFT JOIN 表名 ON 条件 右连接 RIGHT JOIN 表名 ON 条件
子查询 IN() 就没有连接表的功能,只是通过逻辑连接的外键 在 from紧接的表名 中需要筛选的列进行提前筛选一次