数据库系统基础
数据库是依照特定数据数据模型组织、存储和管理数据的文件集合。
数据库文件与文件系统中普通数据文件不同:
- 数据一般不重复存放;
- 可支持多个应用程序并发访问;
- 数据结构独立于使用它的应用程序;
- 对数据增、删、改、查操作均有数据库系统软件进行管理和控制。
数据模型是一种描述事物对象数据特征及其结构的形式化表示。
数据模型由三部分组成:
- 数据结构:描述事物的静态特征,是数据模型的基础。
- 数据操作:描述事物的动态特征。
- 数据约束:描述事物对象的数据之间语义的联系,以及数据取值范围等规则,从而确保数据的完整性、一致性和有效性。
数据库所使用的数据模型:
- 层次数据模型:树结构
- 网状数据结构:图结构
- 关系数据模型:关系二维表结构
数据库系统是一种基于数据库进行数据管理与信息服务的软件系统。
数据库系统由四部分组成:
- 用户:最终用户、DBA用户。
- 数据库应用程序:在DBMS支持下对数据库进行访问和处理。
- 数据库管理系统:操作界面层、语言翻译处理层、数据存取层、数据存储层。
- (关系)数据库:用户数据、元数据、索引数据、运行数据。
数据库应用系统的结构:
- 单用户结构:简单业务服务系统,应用程序和数据库安装在一计算机上。
- 集中式结构:多终端业务服务系统,所有处理操作在服务器集中处理。
- 客户/服务器结构:多终端业务服务系统,处理操作分布在客户机和服务器中。
- 分布式结构:大规模、跨地区的机构信息系统,实现数据分布和处理分布。
数据库管理系统属于系统软件。
典型的数据库管理系统:
- Microsoft SQL Server:通用关系数据库管理系统。
- Oracle DataBase:企业级关系数据库管理系统。
- MySQL:最流行的开源关系数据库管理系统,被许多中小企业信息系统采用。
- PostgreSQL:开源的对象-关系数据库管理系统,支持面向对象数据管理。
PostgreSQL数据库对象:schema、表、视图、序列、函数、触发器。
在PostgreSQL数据库中,表对象有三种类型:关系表、继承表、外部表。
数据库关系模型
关系特征:
- 表中每行存储实体的一个实例数据;
- 表中每列表示实体的一项属性;
- 表中单元格只能存储单个值;
- 表中不允许有重复行和重复列;
- 表中行和列的顺序可任意。
关系模型是一种采用关系二维表的数据结构形式存储实体及其实体间联系的数据模型。
在关系模型中,与关系相关的概念:
- 关系表:具有关系特征的二维表。
- 元组:在关系二维表中的一行,称为一个元组。
- 属性:在关系二维表中的列,称为属性。
- 域:属性列的取值范围。
- 基数:一个值域的取值个数。
- 实体:包含数据特征的事物抽象。
关系是D1×D2×……×Dn笛卡尔积元组集合中有特定意义的子集合。
R(D1,D2,……,Dn):R为关系的名称;D1,D2,……,Dn为关系的属;n为关系的个数,称为元数或度数;n个属性的关系称为n元关系。
关系代数的操作运算(传统的集合运算):
- 并、交、差、广义笛卡尔积。
关系代数的操作运算(专门的关系运算):
- 选择:过滤行。
- 投影:过滤列。
- 连接:从两个关系的笛卡尔积中选取属性间满足一定条件的元组集合。
θ连接:满足比较关系θ。
自然连接:比较的分量是相同的属性组,消除重复的属性列。
外连接:保存未匹配属性值的对应元组,用空值填充。 - 除:被除关系在不相同属性组做投影,满足除的条件。
关系模型的数据完整性约束:
- 实体完整性:主键属性不能取空值,且取值唯一。
- 参照完整性:外键取值与主键值相匹配。
- 用户自定义完整性:域的数据类型与取值范围、属性的数据类型与取值范围、属性的默认值、属性是否允许取空值、属性取值的唯一性、属性间的数据依赖性。
数据库操作语言SQL
PostgreSQL主要数据类型:
- varchar(n):可变长度字符串,长度最大为n
- char(n):固定长度字符串
- date:日期
- money:货币
- numeric(p,d):定点数,p为总位数,d为小数位数
- serial:自增序列整数
创建数据库:
create database <数据库名>;
修改数据库:
alter database <数据库名> [option];
alter database <数据库名> rename to <新数据库名>;
删除数据库:
drop database <数据库名>;
提示:drop database语句不能用在存储过程、触发器、事务处理程序中。
创建数据库表:
create table <表名>
( <列名1> <数据类型> [列完整性约束],
<列名2> <数据类型> [列完整性约束]
);
提示:列约束缺省时默认允许空值,主键默认必须有值。
列约束关键字:
create table <表名>
( <列名1> <数据类型> primary key,
<列名2> <数据类型> not null unique,
<列名3> <数据类型> check(<列名3> in (<取值范围>)),
<列名4> <数据类型> default <默认值>
);
表约束关键字:
create table <表名>
( <列名1> <数据类型> [完整性约束],
<列名2> <数据类型> [完整性约束],
constraint <主键约束名称> primary key(<列名1>,<列名2>)
);
表约束定义代理键:
create table <表名>
( <列名> serial not null,
constraint <主键约束名称> primary key(<列名>)
);
表约束定义外键:
create table <表名>
( <列名> serial not null,
constraint <外键约束名称> foreign key(<列名>)
references <关联表(主键列名)> on delete cascade
);
修改数据库表:
alter table <表名> <修改方式>;
alter table <表名> add <新列名> <数据类型> [完整性约束];
alter table <表名> drop column <列名>;
alter table <表名> drop constraint <完整性约束>;
alter table <表名> rename to <新表名>;
alter table <表名> rename <原列名> to <新列名>;
alter table <表名> alter column <列名> type <新数据类型>;
删除数据库表:
drop table <表名>;
提示:drop table必须先删除foreign key约束或引用的外表后,才能删除主表。
创建索引:
create index <索引名> on <表名(列名)>;
提示:索引是一种针对表中指定列值进行排序的数据结构,可以加快表中数据查询。
修改索引:
alter index <索引名> rename to <新索引名>;
删除索引:
drop index <索引名>;
插入数据:
insert into <表名[(列名)]> values(列值);
提示:char、varchar、date等类型的列值必须使用单引号。
更新数据:
update <表名> set <列名1> = <表达式1> [where <条件表达式>];
提示:如果没有where条件,将更新所有行中的该列值。
删除数据:
delete from <表名> [where <条件表达式>];
提示:如果没有where条件,将删除所有行中的数据。
查询数据:
select [all|distinct] <列名> [into <新表名>]
from <表名>
[where <条件表达式>];
提示:all查询所有数据,distinct消除重复数据。
提示:指定列名实现投影操作过滤列,where条件实现选择操作过滤行。
where子句条件:
where Birthday between ‘2000-01-01’ and ‘2000-12-30’;
where Birthday > ‘2000-01-01’ and Birthday <> ‘2000-04-01’;
where Name like ‘林_’;
where Major not like ‘计算机%’;
提示:通配符(_)代表一个未指定的字符,通配符(%)代表多个未指定的字符。
查询结果排序:
order by <列名> [ASC|DESC];
提示:ASC表示升序,DESC表示降序,默认升序。
查询结果分组:
select Major as 专业, count(StudentID) as 学生人数
from Student
group by Major [having count(*) > 3];
提示:having条件限定分组数据,内置函数不允许出现在where条件中。
使用内置函数:
聚合函数:
select count(distinct Major) as 学生专业数
from Student;
select min(Birthday) as 最早出生, max(Birthday) as 最晚出生
from Student;
算术函数:
select <列名1>, <列名2>, round(Grade, 0) as 成绩四舍五入
from Grade;
字符串函数:
select <列名1>, <列名2>, length(Email) as 邮箱长度
from Student;
提示:空格也会作为一个字符,可以用ltrim()、rtrim()函数去掉空格字符。
提示:输入类型可以是字符串类型或数值类型,输出类型是字符串类型。
日期时间函数:
select date_part(‘yaer’, current_date) as 年;
数据类型转换函数:
select <列名1>, <列名2>, to_char(Grade, ‘99’) as 成绩2位字符
from Grade;
提示:第一个参数是待格式化的值,第二个参数是定义输出或输入格式的模板。
查询多表数据:
子查询:
select * from Teacher where CollegeID in
( select CollegeID from College where CollegeName = ‘计算机学院’
);
多表关联查询:
连接查询:
select C.CollegeName as 学院名称, T.TeacherName as 姓名
from College as C, Teacher as T
where C.CollegeID = T.CollegeID;
JOIN…ON查询:
select C.CollegeName as 学院名称, T.TeacherName as 姓名
from Teacher as T
join College as C on C.CollegeID = T.CollegeID;
授予权限:
grant <权限列表> on <数据库对象> to <用户/角色>;
收回权限:
revoke <权限列表> on <数据库对象> from <用户/角色>;
拒绝授予权限:
deny <权限列表> on <数据库对象> to <用户/角色>;
创建视图:
create view <视图名>[(列名)] as <select查询结果集>;
删除视图:
drop view <视图名>;
视图是一种从基础数据库表中获取数据所组成的虚拟表,对视图的操作就是对表的操作。
使用视图这种对象模式,用户可以获得以下好处:
- 使用视图简化复杂SQL查询操作;
- 使用视图提高数据访问安全性;
- 提供一定程度的数据逻辑独立性;
- 集中展示用户所感兴趣的特定数据;
数据库设计与实现
E-R模型是一种描述现实世界概念数据模型、逻辑数据模型的有效方法。
E-R模型的基本元素:
- 实体:包含数据特征的对象。
- 属性:实体的数据特征。
标识符:唯一标识不同实体实例的属性或属性集。 - 联系:一个或多个实体之间的关联关系。
实体联系类型:
- 多重性分类:一对一联系、一对多联系、多对多联系。
- 参与性分类:可选联系、强制联系。
- 继承性分类:非互斥继承联系、互斥继承联系,完整继承联系、非完整继承联系。
一个实体的存在必须以另一个实体的存在为前提,前者被称为弱实体,后者被称为强实体。
- 标识符依赖弱实体:成绩实体的标识符取决于学生实体和课程实体的标识符。
- 非标识符依赖弱实体:订单实体的标识符不取决于客户实体和商品实体的标识符。
数据库设计策略:
- 自底向上策略:适合于组织机构规模小,业务数据关系简单的数据库设计。
- 自顶向下策略:适合于组织机构规模大,业务数据关系错综复杂的数据库设计。
- 由内至外策略:自底向上策略的特例,先确定关键业务的数据模型,再考虑相关业务。
- 混合设计策略:融合以上多种设计策略。
数据库设计过程:
- 数据需求分析:系统数据需求文档、数据字典。
- 数据库建模设计:概念设计、逻辑设计、物理设计。
- 数据库实现:可运行的数据库系统。
系统数据架构:
- 概念数据模型(CDM):数据被抽象为实体,以模型图形式反映数据对象及其关系。
- 逻辑数据模型(LDM):考虑数据对象在数据库系统中的逻辑表示。
- 物理数据模型(PDM):描述数据模型在特定DBMS中的具体设计实现方案。
概念数据模型设计:
- 抽取与标识实体;
- 分析与标识实体联系;
- 定义实体属性与标识符;
- 检查与完善概念数据模型。
逻辑数据模型设计:
- CDM/LDM转换:消除多对多联系,明确主键标识符和外键标识符;
- 规范化与完善逻辑数据模型。
物理数据模型设计:
- 实体到关系表的转换;
- 弱实体到关系表的转换;
- 实体联系的转换。
数据冗余指一组数据重复出现在数据库的多个表中。
规范化数据库设计有以下好处:
- 减少冗余数据,同一数据在数据库中仅保存一份;
- 设计合理的表间依赖关系和约束关系,便于实现数据完整性和一致性;
- 设计合理的数据库结构,便于系统对数据库的高性能访问处理。
非规范化关系存在问题:插入数据异常、删除数据异常、修改数据异常。
非规范化关系存在问题的根本原因:一个关系表中存在两个或多个主题信息数据。
函数依赖理论:
- 函数依赖:Y依赖于X,X称为决定因子,Y称为函数依赖。
- 平凡函数依赖:Y依赖于X,Y是X的子集。
- 非平凡函数依赖:不是平凡函数依赖的情况。
- 完全函数依赖:Y依赖于X,Y不依赖于X的任何真子集。
- 部分函数依赖:不是完全函数依赖的情况。
- 传递函数依赖:Y依赖于X,Z依赖于Y,Y与X不是一一对应的。
- 多值依赖:X对应多个Y,X对应多个Z,Y和Z相互独立。
规范化范式(NF):关系表符合特定规范化程度的模式。
- 1NF:关系表的属性列不能重复,每个属性列都是不可分割的基本数据项。
- 2NF:消除部分函数依赖,关系表中的所有数据都要和主键有完全函数依赖。
- 3NF:数据操作异常问题,消除传递函数依赖。
- BCNF:数据冗余问题,关系表中所有函数依赖的决定因子必须是候选键。
- 4NF:消除多值依赖。
- 5NF:消除连接依赖。
逆规范化处理的方案:
- 关系表的合并、冗余列的增加、抽取表的创建、关系表分区的创建。
对联机分析处理类型数据库采用低度规范化,对联机事务处理类型数据库采用高度规范化。
数据库管理
事务:单个逻辑处理单元的一组数据库访问操作,要么都被成功执行,要么都不执行。
事务的ACID特性:原子性、一致性、隔离性、持续性。
事务操作:
- 事务开始:begin;
- 事务回滚:rollback [保存点名];
- 事务提交:commit;
- 事务保存点:savepoint <保存点名>;
不是所有的SQL语句都能放在事务程序中执行,默认每条SQL语句都单独构成事务。
并发控制问题:
- 脏读:一个事务读取另一个事务未提交的修改数据,导致使用错误数据。
- 不可重复读:一个事务先后读取的数据期间被修改或删除,造成两次读取结果不一致。
- 幻像读:一个事务先后读取的数据期间被新增,造成第二次多读取数据。
- 丢失更新:一个事务对数据的更新被被其他事务修改,造成读取结果与更新值不一致。
DBMS的并发控制调度器控制各个事务的数据读写操作指令按照特定顺序执行。
可串行化调度:事务调度顺序的执行结果与事务串行的执行结果一样。
资源锁定类型:
- 排他锁定(Lock-X):限制其他事务对共享数据的修改、删除、读取操作。
- 共享锁定(Lock-S):允许其他事务对共享数据的读取操作。
基于锁的并发控制协议:
- 一级加锁协议:修改数据前执行排他锁定,事务处理结束解锁,解决丢失更新问题。
- 二级加锁协议:读取操作前执行共享锁定,读取操作后解锁,解决脏读问题。
- 三级加锁协议:读取操作前执行共享锁定,事务处理结束解锁,解决不可重复读问题。
两阶段锁定协议:在增长阶段只能加锁不能解锁,在缩减阶段只能解锁不能加锁。
事务隔离级别:
- 读取未提交:隔离级别最低,并发性最高。
- 读取已提交:解决脏读问题。
- 可重复读:解决脏读、不可重复读问题。
- 可串行化:解决脏读、不可重复读、幻像读、丢失更新问题。
创建用户:
create user <用户名>
superuser|nosuperuser --超级用户
created|nocreatedb --创建数据库权限
createrole|nocreaterole --创建角色权限
inherit|noinherit --继承权限
login|nologin --登录权限
replication|noreplication --复制权限
bypassrls|nobypassrls --绕过行安全策略权限
connection limit <connlimit> --数据库连接数目限制
password <password> --密码
in role <角色>; --用户作为哪些角色的成员
创建角色:
create role <角色名>
role <角色名> --角色作为哪些角色的组成员
user <用户名>; --角色作为哪些用户的角色
提示:用户默认具有登录权限,角色默认不具有登录权限。
修改用户:
alter user <用户名> [option];
alter user <用户名> rename to <新用户名>;
alter user <用户名> set <参数项> = <参数值>;
alter user <用户名> reset <参数项>;
删除用户:
drop user <用户名>;
实用程序工具备份:
- pg_dump:备份单个数据库、schema、数据库表。
- pg_dumpall:备份整个数据库集群及系统全局数据库。
备份文件:
pg_dump [连接选项] [一般选项] [输出控制选项] <数据库名>
pg_dump -h localhost -p 5432 -U postgres -f G:\ProjectDB.sql ProjectDB
pg_dumpall [连接选项] [一般选项] [输出控制选项]
实用程序工具恢复备份:
- psql:恢复SQL文本格式的数据备份文件。
- pg_restore:恢复自定义压缩格式、TA包R格式或目录格式的数据备份文件。
恢复备份文件:
psql [连接选项] -d <数据库名> -f <备份文件>
pg_restore [连接选项] [一般选项] [恢复控制选项] <备份文件>
数据库应用编程
提供数据库接口的中间件:
- ODBC:开放数据库连接
- JDBC:Java数据库连接
- ADO.net:.net框架下的和数据库交互的面向对象类库
- PDO:PHP数据对象
创建存储过程:
create function <存储过程名>([参数模式] [参数名] [参数数据类型])
return <返回值数据类型> as $$
declare --声明局部变量
<变量名> <变量数据类型> [not null] [:= 初始值];
begin
--函数体语句
end;
$$ language plpgsql;
创建触发器:
create trigger <触发器名> before|after <触发事件> on <表名>
[for each row|statement]
[when 条件]
execute procedure <触发器函数名>;
删除触发器:
drop trigger <触发器名> on <表名> [cascade|restict];
NoSQL数据库技术
NoSQL理论基础:
- CAP理论:一致性、可用性、分区容忍性。
- BASE模型:基本可用、软状态、最终一致性。
- 最终一致性理论:因果一致性、读一致性、会话一致性、单调读一致性、单调写一致性。
NoSQL数据库分类:
- 键值对存储方式:Redis
- 列存储方式:HBase
- 文档存储方式:MongoDB
- 图形存储方式:Neo4j