一、数据库三大范式
1. 第一范式:
所谓第一范式(1NF)是指数据库表的每一列都是不可分割的基本数据项,同一列中不能有多个值,即实体中的某个属性不能有多个值或者不能有重复的属性。如果出现重复的属性,就可能需要定义一个新的实体,新的实体由重复的属性构成,新实体与原实体之间为一对多关系。在第一范式(1NF)中表的每一行只包含一个实例的信息。
- 简而言之:
数据库表中的字段都是单一属性的,不可再分。这个单一属性由基本类型构成如:CHAR, INT, FLOAT ,DOUBLE , DATATIME 等。
2. 第二范式:
第二范式(2NF)是在第一范式(1NF)的基础上建立起来的。第二范式(2NF)要求数据库表中的每个实例或行必须可以被惟一的区分。为实现区分通常需要为表加上一个列,以存储各个实例的惟一标识。要求实体的属性完全依赖于主关键字。
简而言之:
非主属性完全依赖于主关键字例如:
假定关系表选课表为 (学号, 课程编号,姓名, 学分,成绩)
主键:(学号,课程编号)
因为(学号)->(姓名),(课程编号)->(学分)。
即(姓名)和(学分)这两个非主属性,不完全依赖于主关键字(学号,课程编号)。
所以不符合第二范式。
3. 第三范式:
在第二范式的基础上,数据表中如果不存在非关键字段对任一候选关键字段的传递函数依赖则符合第三范式。
简而言之:
不存在传递依赖。例如:
假定课程信息表: (课程编号, 课程名称, 学分,教师姓名,教师职称,教师电话)
主键:(课程编号)
该数据表符合第二范式,不符合第三范式。
因为存在(课程编号)-> (教师姓名) -> (教师职称,教师电话)的传递依赖。
为了使其符合第三范式,可以将其分为2个表:
课程信息表:(课程编号, 课程名称, 学分,教师姓名);
教师信息表:(教师姓名,教师职称,教师电话)。
二、数据库事务(ACID)
1. 原子性(Atomicity):
整个事务中的所有操作,要么全部完成,要么全部不完成,不可能停滞在中间某个环节。事务在执行过程中发生错误,会被回滚(Rollback)到事务开始前的状态,就像这个事务从来没有执行过一样。
2. 一致性(Correspondence):
在事务开始之前和事务结束以后,数据库的完整性约束没有被破坏。
3. 隔离性(Isolation):
隔离状态执行事务,使它们好像是系统在给定时间内执行的唯一操作。如果有两个事务,运行在相同的时间内,执行 相同的功能,事务的隔离性将确保每一事务在系统中认为只有该事务在使用系统。这种属性有时称为串行化,为了防止事务操作间的混淆,必须串行化或序列化请
求,使得在同一时间仅有一个请求用于同一数据。
4. 持久性(Durability):
在事务完成以后,该事务所对数据库所作的更改便持久的保存在数据库之中,并不会被回滚。
三、连接的种类
1.外连接
1.1左连接(left join 或 left outer join)
左向外联接的结果集包括 LEFT OUTER子句中指定的左表的所有行,而不仅仅是联接列所匹配的行。如果左表的某行在右表中没有匹配行,则在相关联的结果集行中右表的所有选择列表列均为空值(null)。
sql语句:
select * from table1 left join table2 on table1.id=table2.id
包含table1的所有记录,根据条件返回table2的相应记录,不符合的为null。
结果:
id | name | id | name |
---|---|---|---|
1 | lee | 1 | 90 |
2 | zhang | 2 | 100 |
4 | wang | null | null |
1.2 右连接(right join 或 right outer join)
右向外联接是左向外联接的反向联接。将返回右表的所有行。如果右表的某行在左表中没有匹配行,则将为左表返回空值。
sql语句:
select * from table1 right join table2 on table1.id=table2.id
包含table2的所有记录,根据条件返回table1的相应记录,不符合的为null。
结果:
id | name | id | name |
---|---|---|---|
1 | lee | 1 | 90 |
2 | zhang | 2 | 100 |
null | null | 3 | 700 |
1.3完整外部联接(full join 或 full outer join)
完整外部联接返回左表和右表中的所有行。当某行在另一个表中没有匹配行时,则另一个表的选择列表列包含空值。如果表之间有匹配行,则整个结果集行包含基表的数据值。
sql语句
select * from table1 full join table2 on table1.id=table2.id
返回左右连接的并集
结果:
id | name | id | name |
---|---|---|---|
1 | lee | 1 | 90 |
2 | zhang | 2 | 100 |
4 | wang | null | null |
null | null | 3 | 700 |
2.内连接(join 或 inner join)
内联接是用比较运算符比较要联接列的值的联接
sql语句:
select * from table1 join table2 on table1.id=table2.id
等价于:
select table1.*,table2.* from table1,table2 where table1.id=table2.id
或者
select * from table1 cross join table2 where table1.id=table2.id
返回符合条件的table1和table2的列。
结果:
id | name | id | name |
---|---|---|---|
1 | lee | 1 | 90 |
2 | zhang | 2 | 100 |
3.交叉连接(cross join)
没有 WHERE 子句的交叉联接将产生联接所涉及的表的笛卡尔积。第一个表的行数乘以第二个表的行数等于笛卡尔积结果集的大小。(没有过滤条件)
例如
select * from table1 cross join table2
等价于:
select * from table1,table2
结果:
id | name | id | name |
---|---|---|---|
1 | lee | 1 | 90 |
2 | zhang | 1 | 90 |
4 | wang | 1 | 90 |
1 | lee | 2 | 100 |
2 | zhang | 2 | 100 |
4 | wang | 2 | 100 |
1 | lee | 3 | 70 |
2 | zhang | 3 | 70 |
4 | wang | 3 | 70 |