数据库期末复习(1-5章)

第1章 概述

目录

引言
什么是数据库系统
什么是数据库
数据独立性
关系系统和其他

1.引言
对数据库可进行的一系列操作:增加、移除、检索、插入、修改、删除数据
DB:包含特殊实体的信息;DBMS:提供这样的方便有效的环境
数据库应用:银行、航空、大学、销售、制造业、人力资源等

2.什么是数据库系统
数据库系统:一个用计算机存储记录的系统
数据库系统的构成:数据、硬件、软件、用户
数据的两大特征:1.集成:至少可以消除部分文件之间的冗余;2.共享:数据库中的每项数据可以被不同的用户共享
硬件部分包含:二级存储设备如I/O设备、设备控制器、I/O通道等;硬件处理器和相应的主存
软件:数据库管理系统(DBMS):数据库管理器、数据库服务器;其他如应用发展工具等软件
用户:应用程序员、最终用户、数据库管理员(DBA)

3.什么是数据库
持久数据:与输入数据、输出数据、控制语句、工作队列等临时数据相区分
数据库:是一个持久数据的集合,这些数据用于某企业的应用系统中
企业如:制造公司、银行、医院、大学、政府部门;持久数据如生产数据、会计数据、病人数据、学生数据、计划数据
其他数据库:联机事务处理、决策支持应用、数据仓库
数据元素:实体与联系;属性
数据描述:数据和数据模型; 数据是一些给定的事实,真命题,数据库是一些真命题的集合;数据模型 是对对象、操作等的一个抽象的、自包含的逻辑定义,这些定义合起来构成了一个面向用户的抽象机
数据管理员(DA)和数据库管理员(DBA):管理层和技术层

为什么使用数据库:
优点:数据共享、减少冗余、避免不一致、提供事务支持、保持完整性、增强安全性、平衡相互冲突的请求、加强标准性

4.数据独立性
定义:应用程序不会因物理表示和访问技术的改变而改变
包含两种类型:物理数据独立性和逻辑数据独立性
数据依赖:有关物理表示的知识和访问技术直接体现在应用程序的代码中
避免应用程序依赖于数据的原因:1.不同的应用程序会从不同角度来看相同的数据;2.DBA必须有权改变物理表示和访问技术以适应变化的需要,而不必改变现有的应用程序
数据的物理表示:存储字段、存储记录、存储文件
可能要改变的各种存储表示:数字数据的表示、字符数据的表示、数字数据的单位、数据编码、数据具体化、存储记录的结构、存储文件的结构

5.关系系统及其他
数据库系统的发展:层次系统(1960s),网状系统(1970s),关系系统(1980s),对象系统,多维方法、基于逻辑的方法和XML方法等

第2章 数据库系统体系结构

目录

引言
三级体系结构
DBA
DBMS
C/S体系结构
实用程序
数据访问处理

1.引言
ANSI/SPARC:数据库管理系统研究组

2.三级体系结构
ANSI/SPARC体系结构分为三层:
内部层:存储层;外部层:用户逻辑层;概念层:公共逻辑层
外部层:
每个用户都有其自己要使用的语言,主语言:如C++、Java等,子语言:数据定义语言(DDL)、数据操纵语言(DML);紧耦合或松耦合的
外部记录和外部视图
概念层:
概念视图表示数据库的全部信息内容
概念模式是概念视图的定义,包含安全性和完整性约束
内部层:
内部视图是整个数据库的低层表示,与物理层仍然不同,并不涉及物理记录的形式,也不考虑具体设备的柱面或磁道大小
内模式是内部视图的定义
映像:
概念模式/内模式:是物理数据独立性的关键;外模式/概念模式:是逻辑数据独立性的关键

3.DBA
DBA的任务:模式定义(逻辑数据库设计)、存储结构和访问方法定义、对模式和物理组织的修改、授予用户访问数据库的权限、指定完整性约束、与用户联络、定义转储和重载机制、监控系统性能并响应不断变化的请求

4.DBMS
是处理数据库访问的软件,包含:数据定义、数据操纵和DML请求(计划或非计划的)、优化和执行、数据安全性和完整性、数据恢复和并发、数据字典、性能
文件管理器系统:并不了解记录的内部数据、很少提供或根本不支持安全性和完整性约束、很少提供或根本不支持恢复和并发控制、没有真正的数据字典的概念、提供很少的数据独立性、不具有统一性或共享性

5.C/S体系结构
服务器:DBMS本身;客户:在DBMS上运行的各种应用程序——用户编写的应用程序和厂商提供的应用程序
B/S体系结构:网络服务器、应用程序服务器、数据库服务器

6.实用程序
载入例程、卸载/重载例程、重组织例程、统计例程、分析例程

7.数据访问处理
程序提交读取请求;DBMS与之交互并分析该请求;DBMS从数据字典中访问三层模式和两个映射;DBMS向OS发送硬盘读取请求;OS向硬盘发送读取请求并获取数据存放于缓存中;数据在DBMS环境下传递到用户的工作空间中;DBMS在程序中返回一个状态词

第3章 关系系统

关系模型的三大方面:结构化:数据库中的数据对用户来说是表,并且只是表;完整性:数据库中的这些表满足一定的完整性约束;操纵性:用户可以使用用于表操作的操作符,选择、投影和连接这三种操作符尤为重要
结构化:
名词:Domain Attribute Tuple Cardinality Degree
Domain:数据类型,用户定义类型和系统定义类型
类型定义:
Type S# Possrep (char);
Type NAME Possrep (char);
Type weight Possren (rational)
类型的两种操作符:
选择子:允许用户通过给定可能表示的每个分量的值,指定或选择类型的一个值
THE_:用户可以利用它来获得类型的值的可能表示的分量

关系和关系变量(RELVARS)
关系:表的数学名词
表头:谓词(一个带参数的真值函数)或真值函数,如表EMP#是姓名为ENAME的雇员,工作在DEPT#部门,工资数额是SALARY
主体:真命题,如雇员E1名为Brown,工作在D1部门,工资数额是40K
关系变量:不同时间的不同关系,分为两种,基本关系变量:实关系变量;视图:虚关系变量,其值依赖于基本关系

目录/字典
各种模式和相应映像存储的地方,有时称为描述信息或元数据
字典是自描述的,即它包括描述字典关系变量自身的条目

关系的性质
1.无重复的元组
2.元组从上到下,没有顺序差别
3.属性由左到右,没有顺序差别
4.每个元组中对应于每个属性都只包含每个属性的一个确定的值

操作
Restrict(select):从表中获取特定的行
Project:从表中获取特定的列
Join:基于共同的列中的共同的值将两个表连接起来
all set-at-a-time:操作数和结果对应整个表
Closure property:一个操作的输出可以成为另一个操作的输入

关系数据库
包含了多种关系的数据库
企业的信息被分解成部分,其中每个关系存储了信息的一部分
例如:account存储了账户信息,depositor存储了哪个客户拥有哪个账户的信息,customer存储了关于客户的信息
表是一种逻辑结构,而不是物理结构
关系数据库遵循的信息原则:数据库全部的信息内容有一种表示方式而且只有一种,也就是表中的行列位置有明确的值。没有连接一个表到另一个表的指针
将所有的信息存储为如下格式:
bank(account-number,balance,customer-name,..)
会导致:信息的重复性(如两个客户拥有一个账户)、空值的需求(表示一个客户没有任何账户)
标准化理论(Chp.10-12)解决了如何设计关系模式的问题

形式化定义:给定集合D1,D2,...Dn,一个关系r是D1×D2×...×Dn的子集,那么一个关系是如下n元组的集合:
(a1,a2,...,an),其中ai∈Di

例如,假设
customer-name={Jones,Smith,Curry,Lindsay}
customer-street={Main,North,Park}
customer-city={Harrison,Rye,Pittsfield}
那么 r={ (Jones,Main,Harrison),(Smith,North,Rye),(Curry,North,Rye),(Lindsay,Park,Pittsfield)}
是customer-name×customer-street×customer-city上的关系

关系模式
A1,A2,...,An是属性,R(A1,A2,...,An)是关系模式
例如Customer-schema (customer-name,customer-street,customer-city)
r(R)是关系模式R上的关系
例如customer(Customer-schema)

语言:SQL、关系代数、关系演算
SQL对DDL的支持:
Create Domain、Create Table、Alter Domain、Alter Table、Drop Domain、Drop Table

第4章 SQL

目录

引言
DDL
查询的基本结构
查询例子
更多复杂的例子
插入、删除、更新
嵌入SQL

1.引言
IBM SYSTEM R SEQUEL -1974~1979
ANSI Standard SQL -1990
ISO Standard SQL -1992
SQL3 (SQL99)
现在更多类SQL语言出现

结构
视图、表、文件
V/T映像:用户定义;T/F映像:系统完成

SQL内容
DDL
DCL:用于完整性和安全性,属于DDL
DML

2.DDL
结构需要创建表、视图(第8章)、索引
Create {table,view,index} <name> <description for that>

索引:
Create index <name> on <table name> ( <index attr name list> )
例如:
Create index l1 on S(S#);     
Create index l2 on S(Sname);
唯一性索引
例如: Create unique index l1 on S(S#);
聚簇索引:使元组的存储尽可能地按照索引值的顺序进行存储,这样当对索引值进行扫描操作时能够减少I/O时间
例如:Create cluster index Cl1 on EMP(E#);

3.基于查询的结构
SQL是基于集合和关系操作的某些修改和增强
一个典型的SQL查询拥有以下结构:
select A1,A2,...,An
from r1,r2,...,rm
where P
Ais代表属性值,ris代表关系,P是个谓词

select语句:用来列举一个查询的结果中所希望获得的属性值
例如:在DEPT关系中查找所有部门的名称,select dname from DEPT
注意:SQL名称是大小写不敏感的,意味着你使用大写或小写都是可以的
SQL中允许关系的重复,这在查询结果中也一样,为了消除重复值,可以在select后插入关键词distinct
例如:在DEPT关系中查找所有部门的名称,并移除重复值, select distinct dname from DEPT
在select语句中可以包含数学表达式+、-、*、/,用于对元组的常数或属性的操作
例如:查询语句 select S#,Sname,Status*2 from S
会返回这样一个关系,它和S关系基本一样,除了Status属性被复制了额外的一份

where语句:由谓词组成,在谓词中包含了出现在from语句后的关系的属性值
例如:查找所有居住在伦敦并且状态值大于20的供应商的供应号码:
select S#
from S
where city='London' AND status>20
比较结果可以通过使用逻辑连接词and,or和not联合起来,也可以应用于数学表达式的结果
SQL还包含了between比较操作,这个操作是为了简化where语句出现某个值大于等于一个值且小于等于另一个值的情况
例如:查找状态值在20和30之间(即≧20,≤30)的供应商的供应号码:
select S#
from S
where status between 20 and 30

from语句:列举了在表达式的评价中要扫描的关系
例如:查找所有雇员和她们的部门信息:
select * 
from EMP,DEPT
where emp.D#=dept.D#

Rename操作
SQL允许通过使用别名 old-name new-name 对关系和属性进行重命名
例如:查找所有供应商的名称、供应号码和供应状态,并重命名列名称S#为number,sname为name:
select sname name, s# Snumber, status
from S

元组变量
例如:查找所有供应商的供应名称和其供应的零件数量:
select sx.sname,spx.P#
from S sx, SP Spx
where sx.S#=spx.s#
元组变量通过在from语句中使用别名来定义


字符串操作:SQL包含了在字符串上进行比较的字符串匹配操作,模式利用两个特殊符号来定义:
percent(%):%字符匹配任何子串
underscore(_):_字符匹配任何字符
例如:查找所有在其城市名称里包含子串“Main"的供应商名称:
select sname
from s
where city like '%Main%'
SQL中还支持一系列字符操作,如连接(“||”)、大小写转换、查找字符串长度、提取子串等

对元组的结果进行排序
例如:列举所有在伦敦的供应商的名称,并按字母表顺序排列
select distinct sname
from S
where city='London'
order by sname
对每个属性,我们指定用desc来表示递减的顺序,用asc来表示递增的顺序,默认为递增顺序,如:order by sname desc

集合操作:包含union、intersect和except,这三种操作都自动消除了重复性
例如:查找所有拥有供应商或零件或两者均有的城市:
(select city from S)
union
(select city from P)
查找所有即拥有供应商又拥有零件的城市:
(select city from S)
intersect
(select city from P)
查找所有拥有供应商但没有零件的城市:
(select city from S)
except
(select city from P)

聚集函数:这些函数用于一个关系的某一列的多重集合的值,并返回一个值
avg:平均值
min:最小值
max:最大值
sum:总合
count:值的个数
例如:查找供应商关系中的元组的数量:
select count(*)
from S
查找供应零件的供应商的数量:
select count(distinct s#)
from SP
查找供应商s1所供应的QTY的平均值:
select avg(QTY)
from SPJ
where s#='s1'
查找每个供应商所供应的QTY的平均值:
select s#,avg(QTY)
from SPJ
Group by s#;
查找每个供应商所供应的零件数量:
select sname,count(distinct p#)
from S,SP
where S.s#=SP.s#
group by sname
注意:在select语句中未使用聚集函数的属性必须添加在group列表中
查找其供应零件的平均值超过600的所有供应商:
select s#, avg(QTY)
from SP
group by s#
having avg(QTY)>600
注意:having语句中的谓词用在group之后,而where语句中的谓词用在group之前
where中不能使用聚集函数,而having中必须使用聚集函数:
select d#,avg(SAL)
from EMP
where age < 40
group by d#
having avg(SAL)>600

空值:可以在元组的某些属性值中使用空值,表示为null,null表示一个未知的值或这个值不存在
任何包含null的数学表达式的结果还是null,如5+null返回null
然而,聚集函数对null值选择了忽视
谓词 is null可以用来检测空值
例如:查找EMP关系中的所有其office#的值是空值的雇员号码:
select E#
from EMP
where office# is null
任何包含null的比较返回未知,如5<null或null<>null或null=null
包含未知值的逻辑运算结果:
OR: (unknown or true) = true, (unknown or false) = unknown, (unknown or unknown) = unknown
AND: (true and unknown) = unknown, (false and unknown) = false, (unknown and unknown) = unknown
NOT: (not unknown) = unknown
如果P的值是未知的,那么命题“P is unknown"是真命题
如果where语句的谓词是unknown的,那么其被认为是false值
对于查询语句 select sum(QTY) from SP,其查询结果忽略了QTY的空值,如果表中没有非空值的QTY,则查询返回null值
除了count(*)之外的所有聚集函数忽略元组中聚集属性的空值

嵌套子查询:SQL提供了嵌套子查询的一套机制,一个子查询是一个嵌套在另一个查询中的select-from-where表达式
子查询通常用于对集合成员、集合比较和集合基数的测试
例如:查找所有工作于销售部门的雇员名称:
select distinct Ename
from EMP
where d# in
    (select d# from DEPT
     where Dname='sale')
集合比较,例如:查找所有工资大于某位经理工资的雇员名称:
select Ename
from EMP
where sal > some
    (select sal 
     from EMP
     where E# in (select mgr
                  from DEPT))
查找所有工资大于所有经理工资的雇员名称:
select Ename
from EMP
where sal > all
    (select sal from EMP
     where E# in (select mgr
                  from DEPT))
集合比较的定义:
F <comp>  some r <=>
存在t∈r s.t. (F <comp> t)
F <comp>  all r <=>
对任意t∈r (F <comp> t)
其中,<comp>可以是:<,≤,>,≥,=,≠
(=some) ≡ in,但是(≠ some) ≠ not in
(≠all) ≡ not in,但是(=all) ≠ in

空关系
exists结构返回true值,如果子查询参数不为空
exists r <=> r ≠ Φ
not exists r <=> r = Φ
X -Y = Φ <=> X∈Y
例如:查找所有位于伦敦的且供应了所有零件的供应商的名称
select distinct Sx.sname
from S Sx
where not exists (
    (select pname
     from P
     where city='London')
   except
    (select Px.pname
     from SP Tx, P Px
     where Tx.p# = Px.p# and
     Sx.S# = Tx.s#)) 
注意:这个查询不能使用=all和它的变量

重复元组的缺失测试
unique限制词测试一个子查询在其查询结果中是否出现冗余的元组
例如:查找至多是一个部门的经理的所有雇员的名称:
select T.Ename
from EMP T
where unique(
    select R.Dname
    from DEPT R
    where T.e#=R.MGR)
查找所有满足其至少有两个雇员的工资大于$500的条件的部门名称:
select distinct T.Dname
from DEPT T
where not unique(
    select R.Ename
    from EMP R
    where T.d#=R.d# and
    R.SAL >= 5000)

Joined关系
Join操作利用两个关系,返回另一个关系作为结果,额外的操作通常在from语句中作为子查询
Join的条件:定义两个关系中的哪个元组相匹配
例如:查找所有工作于销售部门的雇员的名称、工资、部门号码、部门名称和地点:
select Ename,SAL,D#,Dname,Location
from EMP,DEPT
where EMP.d#=DEPT.D#
    And Dname='sales';
查找在相同城市的所有供应商和零件:
Select s#,sname,p#,city,status
From S,P
Where S.city=P.city
查找所有工资超过其经理工资的雇员:(Join 自身)
Select e.Ename,e.SAL,m.Ename,m.SAL
From EMP e, EMP m
Where e.MGR = m.E#
AND e.SAL > m.SAL;

相同的两种查询:
select distinct Ename
from EMP
where d# in
    (select d# from DEPT
     where Dname='sale')

select distinct Ename
from EMP,DEPT
where EMP.D#=DEPT.D#
AND Dname='sale')
查找所有在每个部门拥有最低工资的雇员:(错误!!!Where SAL in在Min(Sal)子查询中可能会得到错误结果)
Select Ename,d#,SAL From EMP
Where SAL in (Select min(SAL)
              From EMP
              Group By d#);
正确结果如下:
Select Ename,d#,SAL From EMP
Where (d#,SAL)
    in (Select d#,min(SAL)
        From EMP
        Group By d#);
查找所有零件号码和它的总数量:
Select p#,sum(QTY) totqty
From SP
Group By p#;
或者
Select p#,(Select sum(QTY)
           From SP
           Where SP.p#=P.p#) totqty
From P;

4.修改—删除

删除所有位于伦敦的供应商:
delete from S
where city='London';
删除所有供应零件p2的供应商:
delete from S
where s# in ( select s#
              from SP
              where p#='p2');
注意:这里会有一些涉及约束的问题,会在Chapter8介绍
删除所有工资在平均值以下的雇员记录:
delete from EMP
where SAL < (select avg (SAL)
                      from EMP);
问题:当我们从EMP中删除元组时,平均工资也随之改变
在SQL中的解决办法:首先,计算工资的avg值,并查找所有需要删除的元组;其次,删除所有在第一步中找到的元组(不重新计算avg值或者重新对元组进行测试)

修改—插入
向S中添加一个新的元组:
insert into S
values('s6','wang ping',20,
       'shanghai');
或者
insert into S(status,city,s#,sname)
values (20,'shanghai','s6','wang ping');
向S中添加一个新的元组,并将其城市设为空:
insert into S
values ('s7','Li hong',30,null);
给所有合肥支行的贷款账户添加一笔$200的账款,其中Account(Account#,Branch-name,Amount):
insert into account
select loan-number,branch-name,200
from loan
where branch-name = 'Hefei';
select from where语句在它的任何结果被插入到关系之前需要被充分评估,否则类似于
insert into table1 select * from table1;的语句会出现问题

修改-更新
对所有工资大于的$4000的雇员增加6%的工资,其他雇员则增加5%的工资:(两个update语句,更新的顺序很重要)
update EMP
set SAL=SAL*1.06
where SAL > 4000;
update EMP
set SAL=SAL*1.05
where SAL <=4000;

5.嵌入SQL
SQL标准定义了SQL在各种编程语言如Pascal,PL/l,Fortran,C和Coblo中的嵌入
EXEC SQL <embedded SQL statement>;
EXEC SQL BEGIN DECLARE SECTION;
Char SQLSTATE[6];
Char P# [6];
int Weight;
EXEC SQL END DECLARE SECTION;
P#='P2';
EXEC SQL Select P.weight INTO :weight
            FROM P WHERE P.P#=:p#;
if SQLSTATE='00000'
Then...
Else...;
更多语句:Cursor语句、Open语句、Fetch语句、Close语句
在主语言中,查找所有供应的数目大于amount变量的供应商名称和其所在的城市:
EXEC SQL
declare c cursor for
select sname,city
from S,SP
where S.s#=SP.s#
and SP.QTY > :amount;
open语句使得查询语句开始执行:EXEC SQL open c;
fetch语句使得查询结果中的一个元组的值被放入到主语言变量中:EXEC SQL fetch c into :cn, :cc;
对fetch语句的重复调用会得到查询结果中的元组的连续值
在SQLCA中的名为SQLSTATE的变量设为'02000'时表示没有更多数据是可用的
SQLSTATE的语句:EXEC SQL WHENEVER <condition> <action>;
Condition: Not found-未找到数据'02000';Sqlerror-发生错误
close语句使得数据库系统删除掉保存在查询结果中的临时关系:EXEC SQL close c;
注意:以上语句的细节和不同的主语言相关
在cursor的定义中使用for update语句可以在之后进行更新:
declare c cursor for
select * 
from EMP
where city='Parise'
for update;
更新:
update EMP
set SAL=SAL+100
where current of c;

动态SQL:允许程序在运行时进行构建和提交SQL,在动态SQL程序中包含了?,其代表了当SQL程序被执行时得到的特定的值
C程序中的动态SQL:
char* sqlprog = "update EMP
                 set SAL = SAL*1.05
                 where d# = ?";
EXEC SQL prepare dynprog
from :sqlprog;
char account[10] = "A-101";
EXEC SQL execute dynprog
using :account;


ODBC:Open DataBase Connectivity标准,应用程序用来连接数据库服务器的标准,是个API,用来打开与数据库的连接、发送查询和更新、返回结果

GUI和spreadsheets等可以使用ODBC
每个支持ODBC的数据库系统提供了一个驱动库,必须连接到客户端程序中;当客户端程序进行一次ODBC API调用时,库中的代码与服务器进行通信,执行查询动作并返回结果;ODBC程序首先分配数据库环境,然后数据库得以连接
使用SQLConnect()进行数据库连接
SQLConnect中的参数:连接句柄、要连接的服务器、用户名、密码
int ODBCexample()
{
    RETCODE error;
    HENV env;    /* environment */
    HDBC conn;    /* database connection */
    SQLAllocEnv(&env);
    SQLAllocConnect(env,&conn);
    SQLConnect(conn,"aura.bell-labs.com",SQL_NTS,"avi",SQL_NTS,"avipasswd",SQL_NTS);
    {...Do actual work...}
    
    SQLDisconnect(conn);
    SQLFreeConnect(conn);
    SQLFreeEnv(env);
}

SQL函数
字符串函数:LOWER(col | value)、UPPER(col | value)、INITCAP(col | value)、CONCAT(char1,char2)、LPAD(col | value, n, 'string')、RPAD(col | value, n, 'string')、SUBSTR(col | value, pos, n)、INSTR(col | value, 'string', pos, n)、LTRIM(col |value, 'char/s')、RTRIM(col | value,'char/s')、SOUNDEX(col | value)、LENGTH(col | value)、TRANSLATE(col | value, from, to)、REPLACE(col | value, string, replacement_string)
数值函数:ROUND(col | n)、TRUNC(col | value, n)、CEIL(col | value)、FLOOR(col | value)、POWER(col | value, n)、EXP(n)、SQRT(col | value)、SIGN(col | value)、ABS(col | value)、MOD(value1, value2)、LOG(m,n)、SIN(n)、TAN(n)、COS(n)
数据函数:MONTHS_BETWWEN(date1,date2)、ADD_MONTHS(date,n)、NEXT_DAY(date1,char)、LAST_DATE(date1)、TRUNC(date1,'char')
转换函数:TO_CHAR(date,'date picture')、TO_NUMBER、TO_DATE、DECODE(col/<exp>,search1,result,[search2,result2,......,]default)
其他函数:NVL(col | value, val)、GRATEST(col | value1, col | value2,...)、LEAST(col | value1, col | value2,...)、VSIZE(col | value)

第5章 数据完整性

目录

引言
四种约束
黄金定律
SQL的支持
断言
触发器

1.引言

完整性约束通过确保对数据库的授权更改不会导致数据一致性的丢失,以防止数据库意外损坏


2.四种约束
类型约束、属性约束、关系变量约束、数据库约束

类型约束
是完整性约束的最基本形式
测试插入在数据库中的值,并测试查询以确保比较具有意义
例如:
TYPE weight POSSREP(RATIONAL)
  CONSTRAINT the_weight(weight)>0.0;

TYPE point POSSREP cartesian(X Rational, Y Rational)
  CONSTRAINT ABS(the_X(point))<=100.0 AND
  ABS(the_Y(point))<=100.0;

属性约束
指定属性为指定类型的声明
例如:
VAR S BASE RELATION(s#     s#,
                   sname   name,
                   status  integer,
                   city	   char)......;

关系变量约束
- 独立关系变量上的约束
- 指定元组是一个指定的关系变量
- 关系变量约束总是立即被检查
例如:
- Constraint sc1
  is_empty(S WHERE city='London'
  AND status != 20)
- Constraint sc2
  is_empty(P WHERE color=color(‘red’)
  AND city != 'London');
- Constraint sc3 count(S) = count(S(s#));
- Constraint sc4
  if NOT(is_empty(P)) then
   count(P WHERE color = color('red'))>0
  end if

数据库约束
- 两种或以上不同关系变量的相互联系
- 二元不同关系变量如何相关
- 约束检查推迟到事务结束
例如:
- Constraint dbc1 is_empty((S JOIN SP)
  WHERE status<20 AND qty>qty(500));
- Constraint dbc2 count(SP (s#))<=count(S (s#));
- Constraint dbc3 count(SP (p#))=count(P (p#));

3.黄金定律
- 如果一个更新操作将使一个关系变量处于违反自身某个谓词的状态,这样的更新是被禁止的

- 正式的或者内部谓词是被用户和系统所理解的
- 关系变量谓词
- 任何时候试图在问题关系变量上的更新都会被系统检查
- 非正式的或者外部谓词被用户所理解,但不被系统所理解

4.码
候选码
- K 是R iff 的候选码
- 唯一性
- 不可还原性
e.g. S(s#) is a key, S(s#,age) is a super key
主码和替换码
- 选择其中一个码作为主码
- 其他被称为候选码
- 主码不能为空
外码
- R2是一个关系变量,R2的外码是R2中的一个集合FK,满足
- 存在一个关系变量R1具有候选码CK
- 在任何时候,R2中的FK中的每个值与在R1的当前值的某些元组的CK值相等
术语:
- 参照
- 参照限制
- 参照元组
- 参照关系变量
- 被参照关系变量
- 自参照、参照环

参照完整性
- 数据库不能包含任何未匹配的外键值
- 定义:
FOREGIN KEY{<item commalist>}
REGERENCES
<relvar name> (<item commalist>)

- 参照行为
ON DELETE
CASCADE/RESTRICT/NO ACTION
ON UPDATE
CASCADE/RESTRICT/NO ACTION
- 触发程序:自动调用在发生特定事件或触发条件的程序

5,SQL的支持
域的约束
- SQL_92中的check语句允许域被约束
- constraint value-test check(value>=4.00)
- 子句constraint value-test是可选的,用于指示某个更新违反的约束
- 可以在域检查中包含复杂的条件
constraint cName-type-test
check(value in
('Shanghai','Beijing'))

check(cityname in 
(select cityname from S))

更多例子:
balance integer check(banlance>=10)

gender char(1) check(gender in ('F','M'))

cnum char(4) check(cnum in
(select cnum
from course))

键约束
- 主键和外键可以作为SOL create table的语句
- create table语句包含的primary key语句包含属性的主键值
- create table语句包含的unique key语句包含属性构成的候选码
- create table语句包含的foreign key语句包含属性构成的外码以及外码的参照值
create table customer
(customer-name char(20),
 customer-street char(30),
 customer-city char(30),
 primary key(customer-name))

 create table branch
 (branch-name char(15) primary key,
 branch-city char(30),
 assets integer);

参照完整性
确保值出现在一个给定的属性也出现在另一个关系的特定属性中
create table account
  (account-number char(10) primary key,
  branch-name char(15),
  balance integer,
  foreign key (branch-name)
  references branch (branch-name)
  )
create table depositor
   ( customer-name char(20),
   account-number char(10),
   primary key (customer-name, account-number),
   foreign key (account-number)
   references account (account-number),
   foreign key (customer-name)
   references customer (customer-name)
   )

级联操作
create table EMP
  ...
  foreign key(D#)
  references DEPT(D#)
  on delete cascade
  on update cascade
  ...)

on delete cascade语句
- 如果删除DEPT中的元组导致参照完整性的破坏,EMP中的级联删除,会删除参照DEPT中的被删除的元组
- cascading updates也相似
 create table account
   (account-number char(10) primary key,
   branch-name char(15),
   balance integer,
   foreign key (branch-name)
   references branch (branch-name)
    ) ON DELETE CASCADE
 create table depositor
   (customer-name char(20),
   account-number char(10),
   primary key (customer-name,account-number),
   foreign key (account-number)
   references account (account-number)
   ON DELETE CASCADE,
   foreign key (customer-name)
   references customer (customer-name)
   ON DELETE CASCADE)
如果有一个依赖于多重关系的外键链,对每个依赖指定的级联删除,删除或更新可以从链的一端传播到整个链
如果一个级联删除导致约束被破坏,且其不能通过进一步的级联操作处理,系统终止事务。结果,所有因事务引起的变化以及其级联操作被撤销了
参照完整性只在事务的最后被检查
中间步骤允许违反参照完整性,但最后的步骤要移除这种违反。否则,就不可能创建一些数据库状态,如插入两个外键互指的元组

替代级联:
on delete set null
on delete set default
外键中的Null值属性复杂化了SQL参照完整性语义,并且最好避免使用
not null:如果一个外键的任何属性是null,元组定义为满足外键约束
Create Table EMPLOYEE(empno number(4) Primary key,
   ename varchar2(10)
   constraint check(ename=upper(ename)),
   job varchar2(14),
   mgr number(4) constraint emp-mgr
   references employee(empno),
   hiredate date defaut sysdate,
   sal number(7,2) not null,
   deptno number(2) not null,
   constraint emp-dept foreign key (deptno)
   references department(deptno)
   ON DELETE SET NULL
   ON UPDATE SET DEFAULT);
Create Table SP(s# s# not null,
   p# p# not null,
   qty qty not null,
   primary key (s#, p#),
   foreign key (s#) references S
   on delete cascade
   on update cascade,
   foreign key (p#) references P
   on delete cascade
   on update cascade,
   check (qty>0 and qty <5001));
Create Table S(s# number(5) primary key,
   sname char(8) unique,
   status number(2),
   city char(20));
Create Table Marrige
  (husband name not null,
  wife name not null,
  mdate date default sysdate,
  primary key (husband,wife));
在create语句后添加约束:
Create Table EMPLOYEE(empno number(4) Primary key,
  ename varchar2(10)
  constraint check (ename=upper(ename)),
  job varchar2(14),
  mgr number(4) constraint emp-mgr 
  references employee(empno),
  hiredate date default sysdate,
  sal number(7.2) not null,
  deptno number(2) not null,
  constraint emp-dept foreign key (deptno)
  references department(deptno)
  ON DELETE SET NULL
  ON UPDATE SET DEFAULT);

6.断言
断言是一个表示条件的谓词,我们希望它永远得到满足
格式:
 create assertion <assertion-name>
      check <predicate>
当一个断言生成时,系统测试它的有效性,并且每次可能违背断言的更新发生时会进行重新测试
这个测试可能会引入很大的负担,因此断言应该小心使用
例如:
1. Create assertion ic1
       check ((select min(status) from S)>4);
2. Create assertion ic2 check
       ( not exists (select * from P
       where NOT (wight>0.0)));
3.  Create assertion ic3 check
       ( not exists (select * from P
       where color = 'red'
       AND city <>'London'));
4. Create assertion ic4 check
       (not exists (select * from P,SP
       where P.p# = SP.p#
       AND (weight*qty) > 20000.0));
5. Create assertion ic5 check
       (not exists (select * from S,SP
       where status <20
       AND S.s# = SP.p#
       AND qty > 500));
每个部门的工资总和必须小于d1部门的所有工资总和:
create assertion sum-constraint check
       (not exists (select * from EMP e2
       where (select sum(sal)
       from EMP e1 where e1.d# = e2.d#
       >=(select (sum(sal)
       from EMP where d# = 'd1')));
每一笔贷款都有至少一个借款人,且借款人保持账户最低余额为1000美元:
 create assertion balance-constraint check
      (not exists (
      select * from loan
      where not exists (
      select * from borrower,depositor,acount
      where loan.loan-number = borrower.loan-number
      and borrower.customer-name=depositor.customer-name
      and depositor.ccount-number=account.account-number
      and account.balance >= 1000)));
注意:每次进行有可能违背断言的更新时都会进行断言测试

7.触发器
触发器是一个声明,是由系统自动执行的数据库修改的副作用
设计一个触发机制,我们必须:
-指定触发器被执行的条件
-指定被触发时执行的动作
触发器在SOL:1999被引入到SQL标准中,但支持更早使用非标准语法的大多数数据库
假设我们允许负的账户余额,银行对透支的解决方式:
- 设置账户余额为0
- 建立在透支额度的贷款
- 给这个贷款账户一个贷款数额,使其等同于透支的数额
执行触发器的条件是对账户关系的更新导致负的账户余额
create trigger overdraft-trigger after update on account
  referencing new row as nrow
  for each row
  when nrow.balance<0
  begin atomic
  insert into borrower
  (select customer-name,account-number
  from depositor
  where nrow.account-number=depositor.account-number);
  insert into loan values (nrow.account-number,
  nrow.branch-name, -nrow.balance);
  update account set balance=0
  where account.account-number=nrow.account-number
  end
触发事件和动作
- 触发事件可以插入、删除和更新
- 触发更新可以被限制到特定的属性
e.g create trigger overdraft-trigger after
     update of balance on account
可以被引用的更新之前和之后的属性值:
referencing old row as : for deletes and updates
 referencing new row as : for inserts and updates
语句级触发器
一个动作可以由一个单一的事务影响的所有行执行,而不是为每个受影响的行执行一个单独的动作
   - 使用 for each statement 而不是 for each row
   - 使用 referencing old table 或 referencing new table来引用包含被影响行的临时表
   - 当使用SQL语句来更新大量rows时更有效
我们有时需要外部世界的行动,如对仓库中数量变少的物品进行重新排序,或在数据库更新触发时打开报警灯
触发器不能直接用于实现外部世界的行动,但触发器可以用来记录在单独的表中要执行的动作,我们可以有一个外部的过程,反复扫描表和进行外部世界的行动
假设一个仓库有如下的表:
inventory(item,amount)
minlevel(item,level)
reorder(item,amount)
orders(item,amount)
create trigger reorder-trigger after update of amount on inventory
       referencing old row as orow, new row as nrow
       for each row
       when nrow.amount <= (select level from minlevel
       where minlevel.item = lrow.item)
       and orow.amount > (select level from minlevel
       where minlevel.item = orow.item)
       begin
       insert into orders (select item, amount
       from reorder where reorder.item = orow.item)
       end
 Triggers in SQL Server Syntax:
create trigger overdraft-trigger on account
     for update 
      as if nrow.balance < 0
      begin
      insert into borrower
      (select customer-name,account-number
      from depositor,inserted
      where inserted.account-number = 
      depositor.account-number)
      insert into loan values
      (inserted.account-number,inserted.branch-name, 
      -inserted.balance)
      update account set balance = 0
      from account,inserted
      where account.account-number = inserted.account-number
      end

Deferred Check推迟检查

DEFERRABLE可延期的
   INITIALLY DEFERRED
   INITIALLY IMMEDIATE
   在每trans开始时定义其状态

NOT DEFERRABLE
 switched on and off
  SET CONSTRAINTS
  <constraint name commalist> <option>;

E.g.
  SET CONSTRAINT ic3 DEFERRED;
COMMIT forces a SET IMMEDIATE for all DEFFERABLE constraints
如果任何完整性检查失败,则回滚事务







已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页