1)什么是存储过程?有哪些优缺点?
存储过程就像是编程语言中的函数一样,封装了我们的代码(PLSQL,T-SQL)
例如:
-------------创建名为GetUserAccount的存储过程----------------
create Procedure GetUserAccount
as
select * from UserAccount
go
-------------执行上面的存储过程----------------
exec GetUserAccount
存储过程的优点:
能够将代码封装起来
保存在数据库之中
让编程语言进行调用
存储过程是一个预编译的代码块,执行效率比较高
一个存储过程替代大量T_SQL语句 ,可以降低网络通信量,提高通信速率
存储过程的缺点:
每个数据库的存储过程语法几乎都不一样,十分难以维护(不通用)
业务逻辑放在数据库上,难以迭代
2)三大范式
思考这样的一个例子:
我们现在需要建立一个描述学校教务的数据库,该数据库涉及的对象包括学生的学号(Sno)、所在系(Sdept)、系主任姓名(Mname)、课程号(Cno)和成绩(Grade),假设我们使用单一的关系模式 Student 来表示,那么根据现实世界已知的信息,会描述成以下这个样子:
但是,这个关系模式存在以下问题:
(1) 数据冗余
比如,每一个系的系主任姓名重复出现,重复次数与该系所有学生的所有课程成绩出现次数相同,这将浪费大量的存储空间。(2)更新异常(update anomalies)
由于数据冗余,当更新数据库中的数据时,系统要付出很大的代价来维护数据库的完整性,否则会面临数据不一致的危险。比如,某系更换系主任后,必须修改与该系学生有关的每一个元组。(3)插入异常(insertion anomalies)
如果一个系刚成立,尚无学生,则无法把这个系及其系主任的信息存入数据库。(4)删除异常(deletion anomalies)
如果某个系的学生全部毕业了,则在删除该系学生信息的同时,这个系及其系主任的信息也丢失了。
总结: 所以,我们在设计数据库的时候,就需要满足一定的规范要求,而满足不同程度要求的就是不同的范式。
第一范式: 列不可分
1NF(第一范式)是对属性具有原子性的要求,不可再分,例如:
如果认为最后一列还可以再分成出生年,出生月,出生日,则它就不满足第一范式的要求。
第二范式: 消除非主属性对码的部分函数依赖
2NF(第二范式)是对记录有唯一性的要求,即实体的唯一性,不存在部分依赖,每一列与主键都相关,例如:
该表明显说明了两个事物:学生信息和课程信息;正常的依赖应该是:学分依赖课程号,姓名依赖学号,但这里存在非主键字段对码的部分依赖,即与主键不相关,不满足第二范式的要求。
可能存在的问题:
数据冗余:每条记录都含有相同信息;
删除异常:删除所有学生成绩,就把课程信息全删除了;
插入异常:学生未选课,无法记录进数据库;
更新异常:调整课程学分,所有行都调整。
正确的做法:
第三范式: 消除非主属性对码的传递函数依赖
3NF(第三范式)对字段有冗余性的要求,任何字段不能由其他字段派生出来,它要求字段没有冗余,即不存在依赖传递,例如:
很明显,学院电话是一个冗余字段,因为存在依赖传递:(学号)→(学生)→(学院)→(学院电话)
可能会存在的问题:
数据冗余:有重复值;
更新异常:有重复的冗余信息,修改时需要同时修改多条记录,否则会出现数据不一致的情况 。
正确的做法:
3)数据库索引
什么是索引?
索引是对数据库表中一个或多个列的值进行排序的数据结构,以协助快速查询、更新数据库表中数据。
你也可以这样理解:索引就是加快检索表中数据的方法。数据库的索引类似于书籍的索引。在书籍中,索引允许用户不必翻阅完整个书就能迅速地找到所需要的信息。在数据库中,索引也允许数据库程序迅速地找到表中的数据,而不必扫描整个数据库。
底层数据结构是什么,为什么使用这种数据结构?
(1)底层数据结构是B+树:
在数据结构中,我们最为常见的搜索结构就是二叉搜索树和AVL树(高度平衡的二叉搜索树,为了提高二叉搜索树的效率,减少树的平均搜索长度)了。然而,无论二叉搜索树还是AVL树,当数据量比较大时,都会由于树的深度过大而造成I/O读写过于频繁,进而导致查询效率低下,因此对于索引而言,多叉树结构成为不二选择。特别地