文章目录
- 一、数据库系统概述
- 二、数据模型
- 2.1E-R数据模型
- 2.2层次数据模型
- 2.3网状数据模型
- 2.4关系数据模型
- 三、数据库系统的体系结构
- 3.1数据库系统体系结构
- 3.2数据库系统
- 3.3数据库管理系统
- 四、关系数据库结构化查询语言——SQL语言
- 4.1基本表定义
- 4.2查询结果显示
- 4.3查询满足条件的元组
- 4.4分组聚集查询
- 4.5连接查询
- 4.6嵌套查询
- 4.7集合查询
- 4.8数据更新
- 4.9视图
- 4.10索引
- 4.11授权控制
- 五、数据库保护
- 5.1事务
- 5.2数据库的完整性,安全性
- 5.3数据库并发控制
一、数据库系统概述
数据库基本概念和特点
数据库是长期存储在计算机内、有组织的、可共享的大量数据的集合。
数据库中的数据按照一定的数据模型组织、描述,具有较小的冗余度、较高的数据独立性和可扩展性,并且可为各种用户所共享。
二、数据模型
2.1E-R数据模型
是一种用于描述实体(Entity)和实体之间关系(Relationship)的数据模型,是现代数据库管理系统中广泛使用的一种数据模型。
矩形表示实体,椭圆表示实体属性,菱形表示实体之间的关系。
2.2层次数据模型
层次模型是一种树形结构,其中父节点可以拥有多个子节点,但每个子节点只能拥有一个父节点。在层次数据模型中,每个节点都可以包含多个属性。由于其树形结构,层次数据模型通常用于处理具有层次结构的数据,例如组织机构。
2.3网状数据模型
网状数据模型是层次数据模型的拓展,它允许每个节点具有多个父节点和多个子节点。在网状数据模型中,节点之间的关系可以是多对多的。由于其复杂性,网站数据模型很少使用。
2.4关系数据模型
关系数据模型是现代数据库管理系统中最常使用的数据模型。在关系数据模型中,数据被组织为表格形式,每个表格包含多个列和行。每列代表一个属性,每行代表一个实例。关系数据模型通常使用结构化查询语言(SQL)进行数据检索和操作,这种数据模型的优点是便于使用和理解,并且能处理大量数据。
面向对象数据模型
面向对象数据模型是一种基于对象概念的数据模型,它将数据组织成对象的集合,每个对象都具有自己的属性和方法。对象可以通过继承、多态和封装等概念相互关联和操作,从而更加自然地表示现实世界中对象和关系。
数据库的体系结构
三、数据库系统的体系结构
3.1数据库系统体系结构
三级模式:
外模式:也称为用户模式或者子模式,是面向用户的数据视图,描述了用户所需的数据,包括数据的组织,访问路径和安全限制等。每个用户可以定义自己的外模式以满足不同的需求。
概念模式:也称为逻辑模式,是整个数据库系统的逻辑结构,描述了数据的总体组织和关系,是外模式和内模式之间的中介层。概念模式包括所有的实体、属性、关系和约束条件,但不涉及具体的存储和实现方式
内模式:也称为存储模式,是数据库的物理系统,描述了数据在存储介质上的存储方式和物理结构。是数据在数据库内部的组织方式。
两级映像:
外模式/概念模式映像:当概念模式改变时,由数据库管理员对各个外模式/概念模式映像做出相应改变,可以使得外模式保持不变。
数据的逻辑结构改变了,应用程序也可不变,保证了数据和程序的逻辑独立性。
概念模式/内模式映像:当数据库存储结构改变时,由数据库管理员对概念模式/内模式做出相应改变,可以使得概念模式保持不变。
数据的物理结构改变了,应用程序也可不变,保证了数据和程序的物理独立性。
3.2数据库系统
数据库系统组成:硬件平台、数据库、软件、数据库管理员
数据库系统分类:关系型数据库、非关系型数据库
3.3数据库管理系统
数据库管理系统:数据库管理系统是数据库系统的核心组成部分,负责管理数据库的所有操作,包括数据的存储、查询、修改和删除等。它是位于用户和操作系统之间的一层数据管理软件。
数据库管理系统功能:
1.数据定义
2.数据组织、存储、管理
3.数据操纵
4.数据库的事务管理和运行
5.数据库的建立与维护
数据库管理系统工作模式:
1、接受应用程序的数据请求和处理请求
2、将用户的数据请求(高级指令)转换成复杂的机器代码(底层指令)
3、实现对数据库的操作
4、从对数据库的操作中接受查询结果
5、对查询结果进行处理(格式转换)
6、将处理结果返回给用户
四、关系数据库结构化查询语言——SQL语言
4.1基本表定义
创建数据库:
create database 学生选课;
打开数据库
use 学生选课;
基本表创建
基本表创建:
学生表创建
create table S
(
sno char(6) primary key,--定义主键primary key
sn char(10) not null,--姓名不能为空值
sd char(16),
sb date,
sex char(2) default '男',--性别默认为男
check (sex in ('男','女'))--检查所填性别是不是在男/女这两选项之间
);
选课表创建
create table sc
(
sno char(6),
cno char(6),
grade dec(4,1),--dec是小数decimal缩写,dec(p,d)表示p位数字组成,小数点后有d位数字
primary key(sno,cno)--一个表有多个主键primary key(主键1,主键2),
foreign key (sno) references s(sno),--定义外键约束
foreign key (cno) references c(cno),--foreign key (属性名1) references 参照表名(属性名2)
check (grade between 0 and 100)--检查成绩是不是在0-100之间
);
课程表创建
create table c
(
cno char(6) primary key,
cn char(10),
pc char(6),
foreign key (pc) references c(cno)
);
基本表修改:
在学生表s中加入一个属性列sh表示学生的籍贯
alter table s add sh char(30);
在学生表s中补充定义sno 为主键
alter table s add primary key(sno);
将基本表s中的学生姓名sn长度修改为12
alter table s alter column sn char(12);
删除基本表s中学生的性别sex属性列
alter table s drop column sex;
基本表删除:
删除基本表s
drop table s cascade;
4.2查询结果显示
投影属性列
查询显示所有学生的信息
select * from s;
去除重复元组
查询选修了课程的学生的学号
select distinct sno from s;
聚集函数
统计学生的总人数
select count(*) from s;
查询选修了课程的学生人数
select count(distinct sno) from sc;
--distinc放count里面,不然你的去重是针对count出来的结果去重,并不是针对sno去重
查询结果的计算
查询所有学生的学号和年龄
select sno 学号,datediff(year,sb,GETDATE())+1 年龄 from s;
--datediff(datepart,startdate,enddate)
--datediff(year,sb,GETDATE()),按照年进行划分,从sb开始,到系统现在时间过了多少年
查询结果的排序
查询所有选修信息
select * from sc ;--默认是按照主键的升序排列
查询所有选修信息,按照课程号升序排列
select * from sc order by cno ;--order by 默认是升序
查询所有选修信息,按照课程号升序排列,同一课程内的学生成绩降序排列
select * from sc order by cno ,grade desc;--如果有多种排列顺序,排列顺序之间加逗号隔开
查询所有学生的学号和年龄,并按年龄升序显示
select sno,datediff(year,sb,getdate())+1 年龄 from s order by 年龄;
4.3查询满足条件的元组
查询选修了课程编号为‘C01’的学生学号和成绩
select sno,grade from sc where cno='C01';
查询“计算机”系“女”同学的学生学号和姓名
select sno,sn from s where sd='计算机' and sex='女';
查询出生时间在1998-01-01到1999-12-31之间的学生姓名和出生时间
select sn ,sb from s where sb between '1998-01-01' and '1999-12-31';
--法二
select sn ,sb from s where sb>='1998-01-01' and sb<='1999-12-31';
查询姓“王”的所有学生学号和姓名
select sno,sn from s where sn like '王%';
查询课程名后缀为“_实验”的课程信息
--查询课程名后缀为"_实验"的课程信息
select * from c where cn like'%\_实验' escape '\';
--_本身是一个内置字符,你如果要把它当普通字符用需要转义
--转义之后需要告诉计算机,我们这里用\转义
--ps:转义字符你用别的也可以,不一定非得用\
查询非数学系和非计算机系的学生学号、姓名和所在系
select sno,sn,sd from s where sd not in('数学','计算机');
查询所有缺少选课成绩的学生学号和对应的课程号
select sno,cno from sc where grade is NULL;
--判断对应属性是不是null,用is,不能用=
4.4分组聚集查询
-查询选修了课程的学生学号和平均成绩
select sno ,avg(grade) from sc group by sno;--默认是按照主键升序
查询平均成绩在90分以上的学生学号和平均成绩
select sd ,count(*)from s where sex='男' group by sd having count(*)>2;
--where这里是还没有分组前先筛选一下,筛选条件是某个系的男生
--然后对系sd分组之后,选择出这个系男生人数大于2的
--分组前加条件where,分组后加条件having,一般group by...和having...配合使用
4.5连接查询
多表连接查询
查询选修课程号为“C01”的学生学号和成绩
select sn,grade from s, sc where cno='C01'and s.sno=sc.sno;
--记得加连接条件,不然多表查询会变成笛卡尔积查询
查询选修“数据结构”课程的学生学号、姓名、成绩
select s.sno,sn,grade from s,sc,c where s.sno=sc.sno and c.cn='数据结构' and c.cno=sc.cno;
外连接查询
查询所有学生姓名以及选修课程号为“C01”的成绩,没有选修该课程的学生,成绩显示为空
select sn ,grade from s left outer join sc on s.sno=sc.sno and cno='C01'
--outer可以省略
select sn ,grade from s left join sc on s.sno=sc.sno and cno='C01'
--外连接的判断条件用on
--左外连接left outer join,outer可不写,左外连接左边的不空,右边表可能有空值
--法二
select sn ,grade from sc right outer join s on s.sno=sc.sno and cno='C01'
查询选修“数据结构”课程的学生学号、姓名、成绩
--法一
select s.sno,sn,grade from s,sc,c where s.sno=sc.sno and c.cn='数据结构' and c.cno=sc.cno;
--法二
select s.sno,sn,grade from s join sc on s.sno=sc.sno and cno=(select cno from c where cn='数据结构');
--法三
select s.sno,sn,grade from (s join sc on s.sno=sc.sno) join c on c.cno=sc.cno where cn='数据结构'
自身连接查询
查询每门课的间接先修课程号(即先修课程的先修课程号)
select c1.cno 课程编号 ,c2.pc 间接先修课程号 from c c1,c c2 where c1.pc=c2.cno ;
4.6嵌套查询
查询选修了“C02”课程的学生姓名
select sn from s ,sc where s.sno=sc.sno and cno='C02';
--法二
select sn from s where sno in(select sno from sc where cno='C02');
查询没有选修‘C02’课程的学生姓名
select sn from s where sno not in(select sno from sc where cno='C02');
查询选修’C01’课程的成绩高于王玲的学生学号和成绩
select sno ,grade from sc where cno='C01' and grade>
(select grade from s,sc where s.sn='王玲'and s.sno=sc.sno and cno='C01');
select sno,grade from sc where cno='C01' and grade>
(select grade from sc where cno='C01' and sno in
(select sno from s where sn='王玲')
)
查询每个学生所修课程成绩超过其所有选课平均成绩的学号和课程号
select sno,cno from sc sc1 where grade >
(select avg(grade) from sc sc2 where sc1.sno=sc2.sno
)
查询其他系中比计算机系某一学生年龄小的学生
--查询其他系中比计算机系某一学生年龄小的学生
select * from s where sb>
any(select sb from s where sd='计算机') and sd!='计算机'
查询其他系中比计算机系学生年龄都小的学生
select * from s where sd !='计算机' and sb> all(select sb from s where sd='计算机');
查询其他系中比计算机系某一学生年龄小的学生
--查询其他系中比计算机系某一学生年龄小的学生
select * from s where sb>
any(select sb from s where sd='计算机') and sd!='计算机';
select * from s where sd!='计算机' and sb>(select min(sb) from s where sd='计算机') ;
查询其他系中比计算机系学生年龄都小的学生
--查询其他系中比计算机系学生年龄都小的学生
select * from s where sd !='计算机' and sb> all(select sb from s where sd='计算机');
select * from s where sd !='计算机' and sb> (select max(sb) from s where sd='计算机');
4.7集合查询
并运算
查询选修了课程号为‘C01’或者‘C02’的学生学号
select distinct sno from sc where cno='C01' or cno='C02';
--法二
select sno from sc where cno='C01'
union
select sno from sc where cno='C02'
--union会自动去重
差运算
查询选修了课程号为’C01’但没有选修‘C02’课程的学生学号
select sno from sc where cno='C01' and sno not in(select sno from sc where cno='C02');
--法二
select sno from sc where cno='C01'
except
select sno from sc where cno='C02'
交运算
查询选修了课程号为‘C01’又选修‘C02’的学生学号
select sno from sc where cno='C01'
intersect
select sno from sc where cno='C02'
--select distinct sno from sc where cno='C01' and cno='C02';
--这种就完全不对,因为不可能有一个元组它同时有C01和C02
--法二
select distinct sno from sc
where sno in(select sno from sc where cno='C01')
and sno in(select sno from sc where cno='C02')
--法三
select sno from sc where cno='C01'and sno in(select sno from sc where cno='C02')
4.8数据更新
插入元组
将一个新学生记录,插入学生关系表S中。(‘S49’,‘王浩浩’,‘计算机’,‘1999-10-16’,‘男’)
insert into s(sno,sn,sd,sb,sex) values('S49','王浩浩','计算机','1999-10-16','男');
--如果是所有属性都插入,也可以不写属性列
insert into s values('S49','王浩浩','计算机','1999-10-16','男');
向表SC中插入一条选课元组(‘S31’,‘C01’)
insert into sc(sno,cno) values('S31','C01');
如果插入的元组有的属性没有给,则默认赋给NULL
插入“计算机”系学生选修“数据库”课程的选课记录
insert into sc(sno,cno)
select sno,cno from s,c where sd='计算机'and cn='数据库';
修改属性值
修改学生表S中“许若”的所在系为“计算机”系
update s set sd ='计算机'where sn ='许若';
将学号为‘S02’的学生所学‘高等数学’的成绩改为93
update sc
set grade=93
where sno='S02' and cno in(select cno from c where cn='高等数学');
若课程成绩低于该课程平均成绩,则将成绩提高5%
update sc set grade=grade*1.05
where grade<
(select avg(grade) from sc sc1 where sc.cno=sc1.cno);
删除元组
删除所有成绩为空值的选课记录
delete from sc where grade is NULL;
--null 在SQL中不代表任何值,通过=null是得不到任何结果的,因此只能用 is null
删除成绩低于所有课程平均成绩的元组
delete from sc where grade <(select avg(grade) from sc );
4.9视图
视图的概念
视图的创建
创建数学系的学生视图
create view M_S(M_SNO,M_SN,M_SB)
as select sno,sn,sb from s where sd='数学';
select * from m_s;
创建学生成绩视图
create view s_grade(sno,sn,cno,grade)
as select s.sno,sn,cno,grade from s,sc where s.sno=sc.sno;
定义由学号及学生的平均成绩构成的视图
create view s_avg(sno,gave)
as select sno,avg(grade) from s_grade group by sno;
视图的删除
视图的查询
视图的更新
视图的作用
4.10索引
4.11授权控制
授予用户U1对表C的更新权限
grant update on c to u1;
授予用户U1对表S的查询权限,并且可以给其他用户授权的权限
grant select on s to u1 with grant option
(以u1登陆),把对学生表S的查询权限授予用户u2
grant select on s to u2
数据库管理员收回用户u1对学生表s的查询权限
revoke select on s from u1;
数据库管理员级联收回用户u1对学生表s的查询权限
ps:级联就是u1授权出去的也要收回
revoke select on s from u1 cascade;
在用户u1具有对学生表s的select权限时,再授予他对视图M_S的select和update权限
grant select,update on M_S to u1;
用户u1修改视图中属性sno值为’S16’的学生姓名为王婷
update M_S set M_SN='王婷'where M_SNO='S16';
五、数据库保护
5.1事务
数据库事务是数据库管理系统(DBMS)中的一个重要概念,是一系列数据库操作的逻辑单元,这些操作要么全部执行成功,要么全部回滚(撤销)。事务具有以下四个属性,通常被称为ACID属性。
原子性(Atomicity):事务是不可分割的工作单位,要么全部执行成功,要么全部回滚。这意味着,如果事务中的任何一条操作失败,整个事务将被回滚到之前的状态。
一致性(Consistency):事务的执行保证数据库从一个一致性状态到另一个一致性状态。即,事务的执行不会破坏数据库的完整性和一致性。
隔离性(Isolation):事务的执行是相互隔离的,每个事务的执行结果不会影响其他事务的执行结果。同时,事务的执行应该遵循一定的隔离级别,例如读未提交、读已提交、可重复读和串行化等。
持久性(Durability):事务的执行结果应该是持久的,即使在系统故障或崩溃的情况下,也应该保证事务的执行结果不会丢失。
5.2数据库的完整性,安全性
完整性:数据库完整性由各种完整性约束来保证。而完整性约束既可以通过DBMS来保障,也可以通过应用程序来实现。如果是基于DBMS,完整性约束将作为关系模式的一部分存入数据库,也就是说,直接在数据库进行定义。
安全性:数据库的安全性是指保护数据库以防止不合法使用所造成的数据泄露、更改或破坏
5.3数据库并发控制
定义:数据的并发控制是指在多个用户同时访问数据库时,如何保证数据的正确性、一致性和完整性。
并发控制手段:封锁
x:排他锁
s:共享锁
死锁与活锁
死锁(Deadlock):是指两个或多个事务都在等待另一个事务释放资源,从而导致所有事务都无法继续执行的情况。简而言之,就是一组事务之间形成了一个相互等待的循环链,导致这些事务都无法执行完成。例如,一个事务占有了某个表中的某一行,而另一个事务则需要占有同一行才能继续执行,此时两个事务就形成了死锁。
活锁(Livelihood)则是指一组事务一直在重试某个操作,但每次操作都失败,最终
无法完成任务的情况。与死锁不同,活锁的事务并没有被阻塞或等待,它们一直在不断重试操作,但都失败了。例如,两个人在狭窄的过道上相向而行,每次都向同一侧
让路,最终导致两人始终无法通过。
两段封锁协议
两段锁协议是指同一事务对任何数据进行读写之前必须对该数据加锁,在释放一个封锁之后,该事务不再申请和获得任何其他封锁。
事务分为两个阶段:
第一阶段是获得封锁,也称为扩展阶段。
第二阶段是释放封锁,也称为收缩阶段。