数据库范式、多表查询,事务
数据库范式
例
学生表
属性 姓名 学号 系名 系主任 课程名称 成绩
基本概念
1.函数依赖 :由A属性(属性组)值可确定B的值,则称B依赖于A,写作A-->B
学号-->系名
2.完全函数依赖: 如果A为一个属性组,且B属性值的确定需要依赖于A组中的所有属性值,则称B完全函数依赖于A
(学号,课程名称)-->成绩
3.部分函数依赖: 如果A是一个属性组,且B只需要A中部分属性值即可确定B属性值,则称B部分依赖A
(学号,课程名称)-->系主任
4.传递函数依赖: 如果通过A属性值可唯一确定B属性值,然后通过B属性值可以唯一确定C属性值,则称C传递函数依赖于A
学号-->系名-->系主任
5.码: 如果在一张表中,一个属性(属性组),被其他所有函数所完全依赖,则称这个属性(属性组)为该表的码
(学号,课程名称)
5.1 主属性: 码属性组中的所有属性
5.2 非主属性: 除过码属性组的属性
1NF: 每一列不可再拆分,原子性
2NF: 消除部分函数依赖
分析可知,若(学号,课程名称)为主属性,那么对主属性部分依赖的有姓名,系名,系主任(只需要学号),将课程名拆
表一:
学生表:属性 姓名 学号 系名 系主任 //主属性 学号
表二:
课程表 : 学号 课程名 成绩 //主属性 学号,课程名
3NF:在2NF基础上,任何非主属性不依赖于其他非主属性(在2NF基础上消除传递依赖)
分析2NF,发现在表一中存在传递依赖 学号-->系名-->系主任
继续拆分表一
表一学生表:
属性 姓名 学号 系名 //主属性 学号
表二课程表 :
学号 课程名 成绩 //主属性 学号,课程名
表三 系表
系名 系主任 //主属性 系名
多表查询
表
1.内连接
1.隐式内连接
SELECT 字段名 FROM 左表, 右表 WHERE 条件
select * from emp,dept where emp.dept_id
= dept.id
;
2.显式内连接
SELECT 字段名 FROM 左表 [INNER] JOIN 右表 ON 条件
//inner可去
select * from emp e [inner] join dept d on e.dept_id
= d.id
;
2.外连接
1.左外连接
SELECT 字段名 FROM 左表 LEFT [OUTER] JOIN 右表 ON 条件
查询的结果是左边表所有数据以及右表中满足ON后条件部分
2.右外连接
SELECT 字段名 FROM 右表 LEFT [OUTER] JOIN 左表 ON 条件
查询的结果是右边表所有数据以及左表中满足ON后条件部分
3.子查询
1.单行单列
查询工资最高的员工是谁
select * from emp where salary = (select max(salary) from emp);
2.多行单列
查询工资大于 5000 的员工,来自于哪些部门的名字
select name from dept where id = (select dept_id from emp where salary > 5000);
3.多行多列
查询出 2011 年以后入职的员工信息,包括部门名称
select * from dept d, (select * from emp where join_date >='2011-1-1') e where d.id
= e.dept_id ;
事务
简单说明
在实际的开发过程中,一个业务操作如:转账,往往是要多次访问数据库才能完成的。转账是一个用户扣钱,另一个用户加钱。如果其中有 1 条 SQL 语句出现异常,则所有的 SQL 语句都要回滚,整个业务执行失败。否则只有扣钱没有加钱,会出错.
事务控制
start transaction; 开启事务
...........操作数据库
commit; //成功更新数据库,整个操作具有了原子性
或者操作失误 rollback//撤销所有操作,不更新数据库
回滚点
savepoint 名字
rollback to 名字
脏读
B读到了A在事务中尚未提交修改后的数据
不可重复读
B在一次事务过程中读到的数据始终不变
一个事务中两次读取的数据内容不一致,要求的是一个事务中多次读取时数据是一致的,这 是事务 update 时引发的问题
幻读
一个事务中两次读取的数据的数量不一致,要求在一个事务多次读取的数据的数量是一致 的,这是 insert 或 delete 时引发的问题