数据库设计的三范式
1、第一范式
数据库表中不能出现重复记录,每个字段是原子性的不能再分
不符合第一范式的示例
存在问题:
最后一条记录和第一条重复(不唯一,没有主键)
联系方式字段可以再分,不是原子性的
关于第一范式,每一行必须唯一,也就是每个表必须有主键,这是我们数据库设计的最基本要求,主要通常采用数值
型或定长字符串表示,关于列不可再分,应该根据具体的情况来决定。如联系方式,为了开发上的便利行可能就采用
一个字段了。
2、第二范式
第二范式是建立在第一范式基础上的,另外要求所有非主键字段完全依赖主键,不能产生部分依赖
示例:
确定主键:
以上虽然确定了主键,但此表会出现大量的冗余,主要涉及到的冗余字段为“学生姓名”和“教师姓名”,出现冗余的
原因在于,学生姓名部分依赖了主键的一个字段学生编号,而没有依赖教师编号,而教师姓名部分依赖了主键的一个 字段教师编号,这就是第二范式部分依赖。
解决方案如下:
学生信息表
教师信息表
教师和学生的关系表
以上是一种典型的“多对多”的设计
3、第三范式
建立在第二范式基础上的,非主键字段不能传递依赖于主键字段。(不要产生传递依赖)
从上表可以看出,班级名称字段存在冗余,因为班级名称字段没有直接依赖于主键,班级名称字段依赖于班级编号, 班级编号依赖于学生编号,那么这就是传递依赖,解决的办法是将冗余字段单独拿出来建立表,如:
学生信息表
班级信息表
以上设计是一种典型的一对多的设计,一存储在一张表中,多存储在一张表中,在多的那张表中添加外键指向一的一方的主键
4、三范式总结
第一范式:有主键,具有原子性,字段不可分割
第二范式:完全依赖,没有部分依赖
第三范式:没有传递依赖
数据库设计尽量遵循三范式,但是还是根据实际情况进行取舍,有时可能会拿冗余换速度,最终用目的要满足客户需
求。
数据库约束
常见的约束
a) 非空约束,not null
b) 唯一约束,unique
c) 主键约束,primary key
d) 外键约束,foreign key
e) 自定义检查约束,check(不建议使用)(在mysql 8.0.16版本之后才起到作用)
事务
1、概述
事务可以保证多个操作原子性,要么全成功,要么全失败。对于数据库来说事务保证批量的 DML 要么全成功,要么全 失败。事务具有四个特征 ACID
a) 原子性(Atomicity)
整个事务中的所有操作,必须作为一个单元全部完成(或全部取消)。
b) 一致性(Consistency)
在事务开始之前与结束之后,数据库都保持一致状态。
c) 隔离性(Isolation)
一个事务不会影响其他事务的运行。
d) 持久性(Durability)
在事务完成以后,该事务对数据库所作的更改将持久地保存在数据库之中,并不会被回滚。
事务中存在一些概念:
a) 事务(Transaction):一批操作(一组 DML)
b) 开启事务(Start Transaction)
c) 回滚事务(rollback)
d) 提交事务(commit)
e) SET AUTOCOMMIT:禁用或启用事务的自动提交模式
当执行 DML 语句是其实就是开启一个事务
关于事务的回滚需要注意:只能回滚 insert、delete 和 update 语句,不能回滚 select(回滚 select 没有任何意义),对于 create、drop、alter 这些无法回滚.事务只对 DML 有效果。
注意:rollback,或者 commit 后事务就结束了。
2、事务的提交与回滚演示
#1、创建表
create table user(
id int (11) primary key not null auto_increment ,
username varchar(30),
password varchar(30)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
#2、查询表中数据
select * from user
#3、开启事务
START TRANSACTION;
#4、插入数据
insert into user (username,password) values (‘zhangsan’,‘123’);
#5、查看数据
select * from user;
#6、修改数据
update user set username=‘lisi’ where id=‘1’;
#7、查看数据
select * from user;
#8、回滚事务
rollback;
#9、查看数据
select * from user;
3、自动提交模式
• 自动提交模式用于决定新事务如何及何时启动。
• 启用自动提交模式:
– 如果自动提交模式被启用,则单条 DML 语句将缺省地开始一个新的事务。
– 如果该语句执行成功,事务将自动提交,并永久地保存该语句的执行结果。
– 如果语句执行失败,事务将自动回滚,并取消该语句的结果。
– 在自动提交模式下,仍可使用 START TRANSACTION 语句来显式地启动事务。这时,一个事务仍可包含多条语句,直到这些语句被统一提交或回滚。
• 禁用自动提交模式:
– 如果禁用自动提交,事务可以跨越多条语句。
– 在这种情况下,事务可以用 COMMIT 和 ROLLBACK 语句来显式地提交或回滚。
• 自动提交模式可以通过服务器变量 AUTOCOMMIT 来控制。
• 例如:
mysql> SET AUTOCOMMIT = OFF;
mysql> SET AUTOCOMMIT = ON;
或
mysql> SET SESSION AUTOCOMMIT = OFF;
mysql> SET SESSION AUTOCOMMIT = ON;
show variables like ‘%auto%’; – 查看变量状态
4、事务的隔离级别
4.1、隔离级别
• 事务的隔离级别决定了事务之间可见的级别。
• 当多个客户端并发地访问同一个表时,可能出现下面的一致性问题:
– 脏读取(Dirty Read)
一个事务开始读取了某行数据,但是另外一个事务已经更新了此数据但没有能够及时提交,这就出现了脏读取。
– 不可重复读(Non-repeatable Read)
在同一个事务中,同一个读操作对同一个数据的前后两次读取产生了不同的结果,这就是不可重复读。
– 幻像读(Phantom Read)
幻像读是指在同一个事务中以前没有的行,由于其他事务的提交而出现的新行。
四个隔离级别
• InnoDB 实现了四个隔离级别,用以控制事务所做的修改,并将修改通告至其它并发的事务:
– 读未提交(READ UMCOMMITTED)
允许一个事务可以看到其他事务未提交的修改。
– 读已提交(READ COMMITTED)
允许一个事务只能看到其他事务已经提交的修改,未提交的修改是不可见的。
– 可重复读(REPEATABLE READ)
确保如果在一个事务中执行两次相同的 SELECT 语句,都能得到相同的结果,不管其他事务是否提交这些修改。
(银
行总账)
该隔离级别为 InnoDB 的缺省设置。
– 串行化(SERIALIZABLE) 【序列化】
将一个事务与其他事务完全地隔离。
视图
1、什么是视图
• 视图是一种根据查询(也就是 SELECT 表达式)定义的数据库对象,用于获取想要看到和使用的局部数据。
• 视图有时也被成为“虚拟表”。
• 视图可以被用来从常规表(称为“基表”)或其他视图中查询数据。
• 建立视图语句的关键部分是查询语句
• 相对于从基表中直接获取数据,视图有以下好处:
– 访问数据变得简单
– 可被用来对不同用户显示不同的表的内容
用来协助适配表的结构以适应前端现有的应用程序
视图作用:
- 提高检索效率
- 隐藏表的实现细节【面向视图检索】
2、创建视图
创建视图的语法为
CREATE [OR REPLACE] [ALGORITHM = {UNDEFINED | MERGE | TEMPTABLE}]
VIEW view_name [(column_list)]
AS select_statement
[WITH [CASCADED | LOCAL] CHECK OPTION]
如下示例:查询员工的姓名,部门,工资入职信息等信息。
select
ename,dname,sal,hiredate,e.deptno
from emp e,dept d
Where e.deptno = e.deptno and e.deptno = 10;
为什么使用视图?因为需求决定以上语句需要在多个地方使用,如果频繁的拷贝以上代码,会给维护带来成本,视图可以解决这个问题
create view v_dept_emp as
select
ename,dname,sal,hiredate,e.deptno
from emp e,dept d
Where e.deptno = e.deptno and e.deptno = 10;
3、修改视图
alter view v_dept_emp as
select
ename,dname,sal,hiredate,e.deptno
from emp e,dept d
where e.deptno = 20;
4、删除视图
drop view 视图名;
触发器
触发器是与表有关的数据库对象,指在 insert/update/delete 之前或之后,触发并执行触发器中定义的SQL语句集合。触发器的这种特性可以协助应用在数据库端确保数据的完整性 , 日志记录 , 数据校验等操作。触发器是一种特殊的存储过程。
使用别名 OLD 和 NEW 来引用触发器中发生变化的记录内容,这与其他的数据库是相似的。现在触发器还只支持行级触发,不支持语句级触发。
存储过程
存储过程和函数是事先经过编译并存储在数据库中的一段 SQL 语句的集合,调用存储过程和函数可以简化应用开发人员的很多工作,减少数据在数据库和应用服务器之间的传输,对于提高数据处理的效率是有好处的
存储过程和函数的区别在于函数必须有返回值,而存储过程没有。
函数 : 是一个有返回值的过程 ;
过程 : 是一个没有返回值的函数 ;
1、创建存储过程
语法:
CREATE PROCEDURE procedure_name ([proc_parameter[,…]])
begin
– SQL语句
end ;
示例:
delimiter $
create procedure pro_test1()
begin
select ‘Hello Mysql’ ;
end$
delimiter ;
2、调用存储过程
call procedure_name() ;
3、删除存储过程
DROP PROCEDURE [IF EXISTS] sp_name ;
索引
MySQL官方对索引的定义为:索引(index)是帮助MySQL高效获取数据的数据结构(有序)。
1、创建索引语法
CREATE [UNIQUE|FULLTEXT|SPATIAL] INDEX index_name
[USING index_type]
ON tbl_name(index_col_name,…)
2、查看索引
show index from table_name;
3、删除索引
DROP INDEX index_name ON tbl_name;
4、索引分类(应用层次上来划分)
1) 单值索引 :即一个索引只包含单个列,一个表可以有多个单列索引
2) 唯一索引 :索引列的值必须唯一,但允许有空值
3) 复合索引 :即一个索引包含多个列
聚集索引和非聚集索引(从表记录的排列顺序和索引的排列顺序是否一致来划分)
聚集索引:就是以主键创建的索引。
非聚集索引:就是以非主键创建的索引(也叫做二级索引)。
扩充:
1)定义:
Char(10): 固定长度,存储ANSI字符,不足的补英文半角空格。
Nchar(10):固定长度,存储Unicode字符,不足的补英文半角空格
varchar:可变长度,存储ANSI字符,根据数据长度自动变化。
nvarchar:可变长度,存储Unicode字符,根据数据长度自动变化。
nvarchar(n) :包含 n个字符的可变长度 Unicode 字符数据。n 的值必须介于 1与4000 之间。字节的存储大小是所输入字符个数的两倍。所输入的数据字符长度可以为零。
varchar[(n)]:长度为 n 个字节的可变长度且非 Unicode的字符数据。n 必须是一个介于1 和 8000之间的数值。存储大小为输入数据的字节的实际长度,而不是 n 个字节。所输入的数据字符长度可以为零。
注意:ANSI主要是以单字节来存储数据,一般适合英文。而我们常用的汉字需要用两个字节来存储,所以就要使用unicode的数据类型,不然读取出来的数据可能会乱码。
(2)区别:
①从存储方式上,nvarchar是按字符存储的,而 varchar是按字节存储的;
②从存储量上考虑, varchar比较节省空间,因为存储大小为字节的实际长度,而 nvarchar是双字节存储;
③在使用上,如果存储内容都是英文字符而没有汉字等其他语言符号,建议使用varchar;含有汉字的使用nvarchar,因为nvarchar是使用Unicode编码,即统一的字符编码标准,会减少乱码的出现几率;
④如果你做的项目可能涉及不同语言之间的转换,建议用nvarchar。
ER图转换为关系模式的一般规则
一、两元联系的转换规则
(1)实体类型的转换
将每个实体类型转换成一个关系模式,实体的属性即为关系的属性,实体标识符即为关系的键。
(2)联系类型的转换
A、实体间的联系是1:1可以在两个实体类型转换成两个关系模式中的任意一个关系模式的属性中加入另一个关系模式的键和联系类型的属性。
B、实体间的联系是1:N则在N端实体类型转换成的关系模式中加入1端实体类型转换成的关系模式的键和联系类型的属性。
C、如实体间的联系是M:N则将联系类型也转换成关系模式,其属性为两端实体类型的键加上联系类型的属性,而键为两端实体键的组合。
二、三元联系的转换规则
(1)1:1:1可以在三个实体类型转换成的三个关系模式中任意一个关系模式的属性中加入另两个关系模式的键(作为外键)和联系类型的属性
(2)1:1:N在N端实体类型转换成的关系模式中加入两个1端实体类型的键(作为外键)和联系类型的属性
(3)1:M:N将联系类型也转换成关系模式,其属性为M端和N端实体类型的键(作为外键)加上联系类型的属性,而键为M端和N端实体键的组合
(4)M:N:P将联系类型也转换成关系模式,其属性为三端实体类型的键(作为外键)加上联系类型的属性,而键为三端实体键的组合
数据库设计
数据库设计(Database Design)是指对于一个给定的应用环境,构造最优的数据库模式,建立数据库及其应用系统,使之能够有效地存储数据,满足各种用户的应用需求(信息要求和处理要求)。在数据库领域内,常常把使用数据库的各类系统统称为数据库应用系统。
按照规范设计,我们将数据库的设计过程分为六个阶段:
•系统需求分析阶段;
•概念结构设计阶段;
•逻辑结构设计阶段;
•物理结构设计阶段;
•数据库实施阶段;
•数据库运行与维护阶段;
需求分析
调查和分析用户的业务活动和数据的使用情况,弄清所用数据的种类、范围、数量以及它们在业务活动中交流的情况,确定用户对数据库系统的使用要求和各种约束条件等,形成用户需求规约。
需求分析是在用户调查的基础上,通过分析,逐步明确用户对系统的需求,包括数据需求和围绕这些数据的业务处理需求。在需求分析中,通过自顶向下,逐步分解的方法分析系统,分析的结果采用数据流程图进行图形化的描述。
概念设计
对用户要求描述的现实世界(可能是一个工厂、一个商场或者一个学校等),通过对其中诸处的分类、聚集和概括,建立抽象的概念数据模型。这个概念模型应反映现实世界各部门的信息结构、信息流动情况、信息间的互相制约关系以及各部门对信息储存、查询和加工的要求等。所建立的模型应避开数据库在计算机上的具体实现细节,用一种抽象的形式表示出来。以扩充的实体—(E-R模型)联系模型方法为例,第一步先明确现实世界各部门所含的各种实体及其属性、实体间的联系以及对信息的制约条件等,从而给出各部门内所用信息的局部描述(在数据库中称为用户的局部视图)。第二步再将前面得到的多个用户的局部视图集成为一个全局视图,即用户要描述的现实世界的概念数据模型。
逻辑设计
主要工作是将现实世界的概念数据模型设计成数据库的一种逻辑模式,即适应于某种特定数据库管理系统所支持的逻辑数据模式。与此同时,可能还需为各种数据处理应用领域产生相应的逻辑子模式。这一步设计的结果就是所谓“逻辑数据库”。
物理设计
根据特定数据库管理系统所提供的多种存储结构和存取方法等依赖于具体计算机结构的各项物理设计措施,对具体的应用任务选定最合适的物理存储结构(包括文件类型、索引结构和数据的存放次序与位逻辑等)、存取方法和存取路径等。这一步设计的结果就是所谓“物理数据库”。
验证设计
在上述设计的基础上,收集数据并具体建立一个数据库,运行一些典型的应用任务来验证数据库设计的正确性和合理性。一般,一个大型数据库的设计过程往往需要经过多次循环反复。当设计的某步发现问题时,可能就需要返回到前面去进行修改。因此,在做上述数据库设计时就应考虑到今后修改设计的可能性和方便性。
运行与维护设计
在数据库系统正式投入运行的过程中,必须不断地对其进行调整与修改。
至今,数据库设计的很多工作仍需要人工来做,除了关系型数据库已有一套较完整的数据范式理论可用来部分地指导数据库设计之外,尚缺乏一套完善的数据库设计理论、方法和工具,以实现数据库设计的自动化或交互式的半自动化设计。所以数据库设计今后的研究发展方向是研究数据库设计理论,寻求能够更有效地表达语义关系的数据模型,为各阶段的设计提供自动或半自动的设计工具和集成化的开发环境,使数据库的设计更加工程化、更加规范化和更加方便易行,使得在数据库的设计中充分体现软件工程的先进思想和方法。