3.1关系模型之关系演算
3.1.1关系元组演算
并运算中:RUS = { r | r
∈
\in
∈R V r
∈
\in
∈S}
差运算中:R-S = { r | r
∈
\in
∈R
∧
\wedge
∧ r
∉
\notin
∈/S}
关系演算: 是以数理逻辑中的谓词演算为基础的,是描述关系运算的另一种思维方式。
SQL语言是继承了关系代数和关系演算各自的优点所形成的
按照谓词变量的不同,可分为关系元组演算和关系域演算。
关系元组演算 :是以元组变量作为谓词变量的基本对象。
关系域演算 :是以域变量作为谓词变量的基本对象。
关系元组演算公式的基本形式 : { t | P(t) }
上式表示: 所有使谓词P为真的元组t的集合
- t是元组变量
- t ∈ \in ∈r表示元组t在关系r中
- t[A]表示元组t的分量,即t在属性A上的值
- P是与谓词逻辑相似的公式,P(t)表示以元组t为变量的公式
关系元组演算公式的完整定义: (递归定义)
- 三种形式的原子公式是公式:s ∈ \in ∈R ; s[A] θ \theta θ c ; s[A] θ \theta θ u[B]
- 如果P是公式,那么 ¬ \neg ¬P也是公式
- 如果P1,P2是公式,则P1 ∨ \vee ∨P2,P1 ∧ \wedge ∧P2也是公式
- 如果P(t)是公式,R是关系,则 ∃ \exists ∃(t ∈ \in ∈R)(P(t))和 ∀ \forall ∀(t ∈ \in ∈R)(P(t))也是公式
- 需要时可加括弧
- 上述运算符的优先次序自高至低为:括弧; θ \theta θ; ∃ \exists ∃; ∀ \forall ∀; ¬ \neg ¬; ∧ \wedge ∧; ∨ \vee ∨
- 公式只限于以上形式
3.1.2关系元组演算公式之原子公式及与,或,非之理解与运用
元组演算公式之原子公式:
1.t
∈
\in
∈R ,例如:{t | t
∈
\in
∈Student}表示查询Student表中所有的元组
2.s[A]
θ
\theta
θ c (
θ
\theta
θ表示比较运算符), 例如:{t | t
∈
\in
∈R
∧
\wedge
∧ t[Sage]<=19
∧
\wedge
∧ t[Sname] = ‘张三’}表示查询R关系中,满足年龄<=19并且名叫张三的所有元组
3.s[A]
θ
\theta
θ u[B],例如{t | t
∈
\in
∈Student
∧
\wedge
∧
∃
\exists
∃(u
∈
\in
∈Student)(t[Sage]>u[Sage])}表示“检索出年龄不是最小的所有同学”
元组演算公式之与,或,非运算符:P(t)可以由公式加运算符与或非递归地构造
3.1.3关系元组演算公式之存在量词与全称量词之理解与运用
存在量词与全称量词公式: 构造P(t)还有两个运算符: ∃ \exists ∃(存在), ∀ \forall ∀(任意)
- 如果F是一个公式,则 ∃ \exists ∃(t ∈ \in ∈r)(F(t))也是公式
- 如果F是一个公式,则 ∀ \forall ∀(t ∈ \in ∈r)(F(t))也是公式
运算符
∃
\exists
∃和
∀
\forall
∀,又称量词,前者称 存在量词 ,后者称 全称量词。
而被这两个运算符限定的元组变量t,或者说,元组变量t前有存在量词或者全称量词,则该变量称为约束变量, 否则称为 自由变量。
3.1.4关系元组演算之应用训练语义正确性与等价性变换训练
元组演算的等价性变换: {t | P(t) }
- P(t)公式,如谓词演算一样,也有一系列演算的等价性
- 例如: ¬ \neg ¬(a = b)——(等价)a<>b
- 再例如或且非运算之间的等价性:1.n个否定的或操作的再否定,便是n个肯定的与操作;2.n个否定的与操作的再否定,便是n个肯定的或操作。
3.1.5关系域演算
关系域演算公式的基本形式:{<x1,x2,…,xn>| P(x1,x2,…,xn)},其中xi代表域变量或常量,P为以xi为变量的公式,公式P可以递归地进行构造:
- 三种形式的原子公式是公式:<x1,x2,…,xn> ∈ \in ∈R ; x θ \theta θ c ; x θ \theta θ y
- 如果P是公式,那么 ¬ \neg ¬P也是公式
- 如果P1,P2是公式,则P1 ∨ \vee ∨P2,P1 ∧ \wedge ∧P2也是公式
- 如果P(t)是公式,x是域变量,则 ∃ \exists ∃(x)(P(x))和 ∀ \forall ∀(x)(P(x))也是公式
- 需要时可加括弧
- 上述运算符的优先次序自高至低为:括弧; θ \theta θ; ∃ \exists ∃; ∀ \forall ∀; ¬ \neg ¬; ∧ \wedge ∧; ∨ \vee ∨
- 公式只限于以上形式
3.1.6关系域演算与关系元组演算的比较
1.元组演算是以元组为变量,以元组为基本处理单位,先找到元组,然后再找到元组分量,进行为此判断;
域演算是以域变量为基本处理单位,先有域变量,然后再判断由这些域变量组成的元组是否存在或是否满足谓词判断;
2.公式的运算符是相同的,只是其中的变量不同
3.元组演算和域演算可以等价互换
3.2 基于关系域演算的QBE语言
3.2.1域演算语言QBE
QBE: Query By Example;
- 特点:操作独特,基于屏幕表格的查询语言,不用书写复杂的公式,只需将条件填在表格中即可。
- 是一种高度非过程化的查询语言
- 特别适合于终端用户的使用
3.2.2QBE的基本形式
QBE操作框架由四个部分构成
- 关系名区:用于书写欲待查询的关系名
- 属性名区:用于显示对应关系名区关系的所有属性名
- 操作命令区:用于书写查询操作的命令
- 查询条件区:用于书写查询条件
3.2.3QBE的操作命令
QBE的操作命令:
- Print或P.——显示输出操作
- Delete或D.——删除操作
- Insert或I.——插入操作
- Update或U.——更新操作
3.2.4QBE的复杂条件书写与示例元素
1.QBE的查询条件:示例元素与投影
示例元素: 条件
θ
\theta
θ参量中的参量也可以是域变量,用任何一个值(不必是结果中的值)带有下划线表示,被称为示例元素,示例元素下划线上面的值不起作用,被当作域变量名称来对待,只用于占位或是连接条件。不带下划线的则是构成实际条件一部分的值。
例如:当不是显示所有内容时,可在条件区对应要显示的列下面书写显示输出命令(即投影运算)
2.QBE的查询条件:用示例元素实现与和或运算
可以采用多行书写,如果是或运算,则打印命令后使用不同的示例元素来表征;如果是与运算,则打印命令后使用相同的示例元素来表征。
3.QBE的查询条件:相当于括号的条件表示
也可以将或且非运算符条件写在操作命令区,此时是对整行条件而言的,相当于将该行条件放在括号中一样。
4.QBE的查询条件:用示例元素实现多个表的连接
当检索涉及多个表时,可利用同一连接条件使用相同的示例元素,来实现多个表的连接
3.3关系演算的安全性
3.3.1什么是关系运算的安全性
关系运算的安全性: 不产生无限关系和无穷验证的运算被称为是安全的
关系代数是一种集合运算,是安全的;集合本身是有限的,有限元素集合的有限次运算仍旧是有限的
关系演算不一定是安全的,R(t)是有限的,但不在R(t)中的元素就可能是无限的,例如t[2]>3是无限的。
3.3.2关系演算的约束
需要对关系演算施加约束条件,即任何公式都在一个集合范围内操作,而不是无限范围内操作,才能保证其安全性
安全约束有限集合DOM: DOM(
ψ
\psi
ψ)是一个有限集合,其中每个符号要么是
ψ
\psi
ψ中明显出现的符号,要么是出现在
ψ
\psi
ψ中的某个关系R的某元组的分量;DOM主要用于约束其中一些谓词的计算范围,它不必是最小集合。
3.3.3安全元组演算表达式
满足下面三个条件的元组演算表达式{t| ψ \psi ψ(t)}称为安全表达式
- 只要t满足
ψ
\psi
ψ,t的每个分量就是DOM(
ψ
\psi
ψ)的一个成员;
-对于 ψ \psi ψ中形如( ∃ \exists ∃u)( ω \omega ω(u))的子表达式,若u满足 ω \omega ω,则u的每个分量都是DOM( ω \omega ω)中的成员
对于 ψ \psi ψ中形如( ∨ \vee ∨u)( ω \omega ω(u))的子表达式,若u不满足 ω \omega ω,则u的每个分量都是DOM( ω \omega ω)中的成员
3.3.4安全域演算表达式
可仿照安全元组演算表达式定义
3.4关于关系运算的一些观点
关系运算有三种:关系代数,关系元组演算和关系域演算。
三种关系运算都是抽象的数学运算,体现了三种不同的思维。
关系代数—以集合为对象的操作思维,由集合到集合的变换
元组演算—以元组为对象的操作思维,取出关系的每一个元组进行验证,有一个元组变量则可能需要一个循环,多个元组变量则需要多个循环。
域演算—以域变量为对象的操作思维,取出域的每一个变量进行验证看其是否满足条件。
1.三种运算之间是等价的:关系代数与安全的元组演算表达式与安全的域演算表达式是等价的。即一种形式的表达式可以被等价地转换为另一种形式
2.三种关系运算都可说是非过程性的:相比之下:域演算的非过程性最好,元组演算次之,关系代数最差。
3.三种关系运算虽是抽象的,但却是衡量数据库语言完备性的基础:一个数据库语言如果能够等价地实现这三种关系运算的操作,则说该语言是完备的。
4.数据库语言可以基于这三种抽象运算来设计:
- 用“键盘符号”来替换抽象的数学符号
- 用易于理解的符号组合来表达抽象的数学符号
以上为课程1:基本知识与关系模型
课程2:数据库语言—SQL
3.5 概览SQL语言
3.5.1 SQL语言的功能概述
SQL语言的功能概述: SQL语言是集DDL,DML和DCL于一体的数据库语言
SQL语言主要由以下9个单词引导的操作语句来构成,但每一种语句都能表达复杂的操作请求:
1.DDL语句引导词:Create(建立),Alter(修改), Drop(撤销)
- 模式的定义和删除,包括定义Database, Table, View, Index,完整性约束条件等,也包括定义对象(RowType行对象,Type列对象)
2.DML语句引导词:Insert, Delete, Update, Select
- 各种方式的更新与检索操作,如直接输入记录,从其他Table输入
- 各种复杂条件的检索,如连接查找,模糊查找,分组查找,嵌套查找等
- 各种聚集操作,求平均,求和,等等,分组聚集,分组过滤等
3.DCL语句引导词:Grant, Revoke
- 安全性控制:授权和撤销授权
交互式SQl—嵌入式SQL—动态SQL等等
3.5.2 利用SQL语言建立数据库
例如: 学生选课数据库SCT
学生:学号S#,姓名Sname,性别Ssex,年龄Sage,所属系别D#,班级Sclass
Student(S# char(8), Sname char(10),Ssex char(2), Sage integer, D# char(2), Sclass char (6))
院系:系别D#,系名Dname,系主任Dean
Dept(D# char(2), Dname char(10), Dean char(10))
课程:课号C#,课名Cname,教师编号T#,学时Chours,学分Credit
Course(C# char(3), Cname char(12), Chours integer, Credit float(1), T# char(3))
教师:教师编号T#, 教师名 Tname,所属院系D#,工资Salary
Teacher(T# char(3), Tname char(10),D# char(2), Salary float(2))
选课:学号S#, 课号C#,成绩Score
SC(S# char(8), C# char(3), Score float(1))
SQL-DDL——建立数据库:定义数据库和表(使用DDL),向表中追加元组(使用DML)
DDL:Data Definition Language
- 创建数据库(DB)—Create Database
- 创建DB中的Table(定义关系模式)—Create Table
- 定义Table及其各个属性的约束条件(定义完整性约束)
- 定义View(定义外模式及E-C映像)
- 定义Index,Tablespace…等(定义物理存储参数)
- 上述各种定义的撤销与修正
DDL通常由DBA来使用,也有经DBA授权后由应用程序员来使用
1.创建数据库的语句—Create Database:
创建Database:
数据库(Database)是若干具有相互关联关系的Table/Relation的集合;
数据库可以看作是一个集中存放若干Table的大型文件
create database的简单语法形式:
———————— create database 数据库名;
示例: 创建课程学习数据库SCT——create database SCT;
2.创建关系/表的语句—Create Table:
创建Table:
create table简单语法形式:
————————Create table 表名(列名 数据类型[Primary key|Unique][Not null]
—————————————————[,列名 数据类型[Not null],…]);
- "[ ]"表示其括起的内容可以省略,“|”表示其隔开的两项可取其一
- Primary key:主键约束。每个表只能创建一个主键约束。
- Unique:唯一性约束(即候选键)。可以有多个唯一性约束
- Not null:非空约束。是指该列允许不允许有空值出现,如选择了Not null表示该列不允许有空值出现
- 语法中的数据类型在SQL标准中有定义:
——在SQL-92标准中定义的数据类型:
1.char(n):固定长度的字符串
2.varchar(n):可变长字符串
3.int:整数//有时不同系统也写作integer
4.numeric(p,q):固定精度数字,小数点左边p位,右边p-q位
5.real:浮点精度数字//有时不同系统也写作float(n),小数点后保留n位
6.data:日期(2003-09-12)
7.time:时间(23:15:03)
…
示例:定义学生表 Student——Create Table Student(S# char(8)not null,Sname char(10),Ssex char(2), Sage integer, D# char(2), Sclass char (6));
定义课程表—— Create Table Course(C# char(3) , Cname char(12), Chours integer, Credit float(1), T# char(3)) ;
SQL-DML:Data Manipulation Language
- 向Table中追加新的元组:Insert
- 修改Table中某些元组中的某些属性的值:Update
- 删除Table中的某些元组:Delete
- 对Table中的数据进行各种条件的检索:Select
- 通常由用户或应用程序员使用,访问经授权的数据库
3.向表中追加元组的值—INSERT INTO:
向表中追加元组-insert into简单语法形式:
——————insert into 表名[(列名[,列名]…]
——————————values(值[,值],…);
- values后面值的排列,须与into子句后面的列名排列一致
- 若表名后的所有列名省略,则values后的值的排列,须与该表存储中的列名排列一致
示例:追加学生表中的元组:Insert Into Student
——————————————Values(‘98030101’,‘张三’,‘男’,20,‘03’,‘980301’);
或:————————————Insert Into Student (S#,Sname,Ssex,Sage,D#,Sclass)
——————————————Values(‘98030102’,‘张四’,‘女’,21,‘03’,‘980301’);
追加课程表中的元组:Insert Into Course
——————————Values(‘001’,‘数据库’,40.6,‘001’);
3.5.3 利用SQL语言进行简单查询
1.单表查询—SELECT FROM WHERE
SQL提供了结构形式一致但功能多样化的检索语句Select
Select的简单语法形式:——Select 列名 [[,列名]…]
——————————————From 表名
——————————————[Where 检索条件];
- 语义:从表名所给出的表中,查询出满足检索条件的元组,并按给定的列名及顺序进行投影显示。
- 相当于:一个关系代数操作
- Select语句中的select…, from… ,where…,等被称为子句,在以上基本形式基础上会增加许多构成要素,也会增加许多新的子句,满足不同的需求
示例:检索学生表中所有学生的信息:Select S#,Sname,Ssex,Sclass, D#
——————————————————From Student;
若投影所有列,则为—————————Select * From Student;
示例:检索学生表中所有年龄小于等于19岁的学生的年龄及姓名:Select Sage, Sname
—————————————————————————————From Student
——————————————————————————————Where Sage<=19;
检索条件的书写: 与选择运算的条件con一样,只是其逻辑运算符用and,or,not来表示,同时也要注意运算符的优先次序及括弧的使用。书写要点是注意对自然语言检索条件的正确理解。
示例:检索教师表中所有工资少于1500元或者工资大于2000元并且是03系的教师姓名
————————Select Tname
————————From Teacher
————————Where (Salary<1500 or Salary>2000) and D#=03‘’;
示例:求后者学过001号课程,或者学过002号课程的学生的学号
————————Select S#
————————From SC
————————Where C#=‘001’ or C#=‘002’;
结果唯一性问题: 关系模型不允许出现重复元组。但现实DBMS,却允许出现重复元组,但也允许无重复元组。
在Table中要求无重复元组是通过定义Primary key或Unique来保证的;而在检索结果中要求无重复元组,是通过DISTINCT保留字的使用来实现的。
示例:在选课表中,检索成绩大于80分的所有学号
错误:Select S# From SC Where Score >80; //若一个学生选多门课程,每门课都满足条件,则结果该学生学号会多次出现
正确:Select DISTINCT S# From SC Where Score >80; //重复元组被DISTINCT过滤掉,只保留一份。
检索结果之排序-SELECT FROM WHERE ORDER BY
结果排序问题:DBMS可以对检索结果进行排序,可以升序排序,也可以降序排序;Select语句中结果排序是通过增加order by子句实现的: order by 列名 [acs|desc] ;意义为检索结果按指定列名进行排序,若后跟asc或省略,则为升序;若后跟desc,则为降序。
示例:按学号由小到大的顺序显示出所有学生的学号及姓名
————————Select S#, Sname
————————From Student
————————order by S# acs;
示例:检索002号课大于80分的所有同学学号并按成绩由高到低顺序显示
————————Select S#
————————From SC
————————Where C# = ‘002’ and Score>80
————————order by Score desc;
模糊查询-SELECT FROM WHERE *LIKE*:
模糊查询问题:比如检索姓张的学生,检索张某某;这类查询问题,Select语句是通过在检索条件中引入运算符like来表示的
含由like运算符的表达式:列名 [not] like ”字符串“
找出匹配给定字符串的字符串。其中给定字符串中可以出现%,_等匹配符
匹配规则:
- ”%“——匹配零个或多个字符
- ”_“——匹配任意单个字符
- ”\“——转义字符,用于去掉一些特殊字符的特定含义,使其被作为普通字符看待
示例:检索所有姓张的学生学号及姓名
——————Select S#, Sname
——————From Student
——————Where Sname Like ”张%“;
示例:检索名字为张某某的所有同学姓名
——————Select Sname
——————From Student
——————Where Sname Like ”张__“;
示例:检索姓名不姓张的所有同学姓名
——————Select Sname
——————From Student
——————Where Sname not Like ”张%“;
3.5.4 利用SQL语言进行多表联合查询
多表联合查询: 多表联合检索可以通过连接运算来完成,而连接运算又可以通过广义笛卡尔积后再进行选择运算来实现。
Select的多表联合检索语句:Select 列名 [[,列名]…]
——————————————From 表名1,表名2
——————————————Where 检索条件;
- From两个表,相当于两个表进行广义笛卡尔积
- 检索条件中要包含连接条件,通过不同的连接条件可以实现等值连接,不等值连接及各种 θ \theta θ-连接
θ
\theta
θ-连接之等值连接:
示例:按“001”号课成绩由高到低顺序显示所有学生的姓名(二表连接)
————————Select Sname From Student,SC
————————Where Student.S#=SC.S# and SC.C#=‘001’
————————order by Score desc;
- 多表连接时,如两个表的属性名相同,则需采用表名.属性名方式来限定该属性是属于哪一个表
示例:按‘数据库’课成绩由高到低顺序显示所有同学姓名(三表连接)
————————Select Sname From Student,SC,Course
————————Where Student.S# = SC.S# and SC.C# = Course.C# and Cname=‘数据库’
————————Order by Score desc;
表更名与表别名: 重名之处理,连接运算涉及到重名的问题,如两个表中的属性重名,连接的两个表重名(同一表的连接)等,因此需要使用别名以便区分
select中采用别名的方式:————Select 列名 as 列别名
————————————————From 表名1 as 表别名,表名2 as 表别名2…
————————————————Where 检索条件;
- 上述定义中的as可以省略
- 当定义了别名后,在检索条件中可以使用别名来限定属性
θ
\theta
θ-连接之不等值连接:
示例:求有薪水差额的任意两位教师
——————————Select T1.Tname as Teacher1, T2.Tname as Teacher2
——————————From Teacher T1, Teacher T2
——————————Where T1.Salary>T2.Salary;
示例:求年龄有差异的任意两位同学的姓名
——————————Select S1.Sname as Stud1,S2.Sname as Stud2
——————————From Student S1,Student S2
——————————Where S1.Sage>S2.Sage;
示例:求既学过“001”号课又学过“002”号课的所有学生的学号
——————————Select S1.S#
——————————From SC S1,SC S2
——————————Where S1.S#=S2.S# and S1.C#=“001” and S2.C#=“002”;
示例:求“001”号课成绩比“002”号课成绩高的所有学生的学号
——————————Select S1.S#
——————————From SC S1,SC S2
——————————Where S1.S#=S2.S# and S1.C#=“001” and S2.C#=“002”
——————————and S1.Score>S2.Score;
3.5.5 利用SQL语言进行增删改
1.SQL-之更新操作:
- 元组新增Insert:新增一个或一些元组到数据库的Table中
- 元组更新Update:对某些元组中的某些属性值进行重新设定
- 元组删除Delete:删除某些元组
- SQL-DML既能单一记录操作,也能对记录集合进行批更新操作
- SQL-DML之更新操作需要利用利用前面介绍的子查询(Subquery)的概念,以便处理“一些”,“某些”等。
2.SQL-之INSERT
元组新增insert命令有两种形式:
1.单一元组新增命令形式:插入一条指定元组值的元组
——————insert into 表名[(列名[,列名]…]
——————————values(值[,值],…);
2.批数据新增命令形式:插入子查询结果中的若干条元组。待插入的元组由子查询给出
——————insert into 表名[(列名[,列名]…]
——————————子查询;
示例:批元组新增
新建立Table:St(S#,Sname),将检索到的满足条件的同学新增到该表中
————————Insert Into St(S#,Sname)
——————————Select S#,Sname From Student
——————————Where Sname like ‘%伟’;
————————Insert Into St(S#, Sname)
——————————Select S#,Sname From Student Order by Sname;
注意:当新增元组时,DBMS会检查用户定义的完整性约束条件等,如不符合完整性约束条件,则将不会执行新增动作。
3.SQL-之DELETE
元组删除Delete命令:删除满足指定条件的元组
——————Delete From 表名 [ Where 条件表达式];
如果Where条件省略,则删除所有的元组。
示例: 删除SC表中所有元组
——————Delete From SC;
删除98030101号同学所选的所有课程
——————Delete From SC Where S#=‘98030101’;
删除自动控制系的所有同学
——————Delete From Student Where D# in
————————(Select D# From Dept Where Dname=‘自动控制’);
————————//此是一简单的嵌套子查询,后面详细解释;
4.SQL-之UPDATE
元组更新Update命令:用指定要求的值更新指定表中满足指定条件的元组的指定列的值
————————Update 表名
————————Set 列名=表达式|(子查询)
——————————[[,列名=表达式|(子查询)]…]
————————[Where 条件表达式];
如果Where条件省略,则更新所有的元组
示例:将所有教师工资上调5%
————————Update Teacher
————————Set Salary = Salary1.05;
示例:将所有计算机系的教师工资上调10%
————————Update Teacher
————————Set Salary = Salary1.1
————————Where D# in
————————————(Select D# From Dept Where Dname=‘计算机’);
3.5.6 利用SQL语言修正与撤销数据库
1.SQL-DDL之撤销与修改
a.修正数据库:修正数据库的定义,主要是修正表的定义
修正基本表的定义:
————————alter table tablename
————————[add {colname datatype,…}] //增加新列
————————[drop{完整性约束名}] //删除完整性约束
————————[modify{colname datatype,…}] //修改列定义
示例:在学生表Student(S#, Sname,Ssex,Sage,D#,Sclass)基础上增加二列Saddr,PID
————Alter Table Student Add Saddr char[40], PID char[18];
示例:将上例表中Sname列的数据类型增加两个字符
————Alter Table Student Modify Sname char(10);
示例:删除学生姓名必须取唯一值的约束
————Alter Table Student Drop Unique(Sname)
b.撤销基本表:drop table 表名;
示例: 撤销学生表Student——Drop Table Student;
注意:SQL-delete语句只是删除表中的元组,而撤销基本表drop table的操作是撤销包含表格式,表中所有元组,由该表导出的视图等相关的所有内容,所以使用要特别注意。
c.撤销数据库:drop database 数据库名;
示例: 撤销SCT数据库————Drop database SCT;
2.SQL-DDL之数据库指定与关闭命令
有些DBMS提供了操作多个数据库的能力,此时在进行数据库操作时需要指定待操作数据库与关闭数据库的功能。
指定当前数据库: use 数据库名;
关闭当前数据库: close 数据库名;
3.5.7 典型DBMS交互环境简介-SQL Server
1.SQL Server简介
SQL Server 的系统数据库:
master: 是SQL Server中最重要的系统数据库,存储SQL server中的元数据(存储我们定义的数据库格式,各种表的格式信息)
model: 模板数据库,在创建新的数据库时,SQL Server将会复制此数据库作为新数据库的基础
msdb: 代理服务数据库,提供一个存储空间
tempdb: 临时数据库,为所有的临时表,临时存储过程及其他临时操作提供存储空间,断开连接时,临时表与存储过程自动被删除
SQL Server的数据库
文件:有三种文件扩展名:.mdf,.ndf,.ldf
- 主数据库文件:扩展名为.mdf,是存储数据库的启动信息和部分或全部数据。一个数据库可以有多个数据库文件,但主数据库文件只有一个。
- 辅助数据文件:扩展名为.ndf,用于放置主数据库文件中所定义数据库的其它数据,可有多个。在数据庞大时,可以帮助存储数据。
- 日志文件:扩展名.ldf。每个数据库至少有一个事务日志文件。
页面:是SQL Server存储的最小单位,一页为8k或8192字节
空间(extent):是8个连续的页面,即64k数据,是分配数据表存储空间的一种单位
3.6 SQL语言之复杂查询与视图
3.6.1 利用SQL语言表达复杂查询—(NOT)IN子查询
1.子查询:为什么需要子查询?
现实中,很多情况需要进行下述条件的判断
- 集合成员资格——某一元素是否是某一个集合的成员
- 集合之间的比较——某一个集合是否包含另一个集合等
- 集合基数的测试——测试集合是否为空;测试集合是否存在重复元组
子查询: 出现在Where子句中的Select语句被称为子查询(subquery),子查询返回了一个集合,可以通过与这个集合的比较来确定另一个查询集合。
三种类型的子查询:
- (NOT)IN-子查询
- θ \theta θ-Some/ θ \theta θ-All子查询
- (NOT) EXISTS子查询
2.IN与NOT IN谓词子查询
(NOT) IN子查询——基本语法: 表达式 [not] in (子查询)
————————语法中,表达式的最简单形式就是列名或常数
————————语义:判断某一表达式的之是否在子查询的结果中
示例:列出张三,王三同学的所有信息
——————Select * From Student
———————Where Sname in (“张三”,“王三”); //此处直接使用了某一子查询的结果集合,如果该集合是已知的固定的,可以如上直接书写
相当于——————Select * From Student
——————————Where Sname = “张三” or Sname= “王三”;
示例:列出选修了001号课程的学生的学号和姓名
——————Select S#, Sname From Student
————————Where S# in (Select S# From SC Where C#=“001”);
示例:求既学过001号课程,又学过002号课程的学生的学号:
Select S# From SC
Where C# =‘001’ and S# in (Select S# From SC Where C#=‘002’);
示例:列出没学过李明老师讲授课程的所有同学的姓名
Select Sname From Student
Where S# not in(Select S# From SC,Course C,Teacher T
————————Where T.Sname=“李明” and SC.C#=C.C# and T.T#=C.T#);
3.非相关子查询
带有子查询的Select语句区分为内层与外层
非相关子查询: 内层查询独立进行,没有涉及任何外层查询相关信息的子查询
4.相关子查询 :内层查询需要依靠外层查询的某些参量作为限定条件才能进行子查询;外层向内层传递的参量需要使用外层的表名或表别名来限定
示例: 求学过001号课程的同学的姓名
Select Sname
From Student Stud
Where S# in (Select S# From SC Where S#=Stud.S# and C#=‘001’);
注意:相关子查询只能由外层向内层传递参数,而不能反之;这也被称为变量的作用域原则。
3.6.2 利用SQL语言表达复杂查询— θ \theta θ-Some与 θ \theta θ-All子查询
基本语法:
————————表达式
θ
\theta
θ some(子查询)
————————表达式
θ
\theta
θ all(子查询)
语法中,
θ
\theta
θ是比较运算符:<,>,<=,>=,=,<>.
语义:将表达式的值与子查询的结果进行比较:
- 如果表达式的值至少与子查询结果的某一个值相比较满足 θ \theta θ关系,则“表达式 θ \theta θ some (子查询)”的结果便为真。
- 如果表达式的值与子查询结果的所有值相比较都满足 θ \theta θ关系,则“表达式 θ \theta θ all(子查询)”的结果便为真
示例:找出工资最低的教师姓名
Select Tname From Teacher
Where Salary <= all (Select Salary From Teacher);
示例:找出001号课成绩不是最高的所有学生的学号
Select S# From SC
Where C#=‘001’ and Score <some (Select Score From SC Where C#=“001”);
示例:找出所有课程都不及格的学生姓名(相关子查询)
Select Sname From Student
Where 60>all(Select Score From SC Where S#=Student.S#);
为什么不用 θ \theta θany : 在SQL标准中,也有 θ \theta θ any谓词,但由于其语义的模糊性:any,“任一”是指所有呢?还是指某一个?不清楚,所以被 θ \theta θ some替代以求更明晰
等价性变换需要注意: 如下两种表达方式含义是相同的‘
——————————表达式 = some (子查询)
——————————表达式 in (子查询)
如下两种表达方式含义却是不同的,请注意:
——————————表达式 not in (子查询)
——————————表达式 < >some (子查询)
与not in 等价的是:表达式 <> all(子查询)
3.6.3 利用SQL语言表达复杂查询—(NOT) EXISTS子查询
基本语法: [not] Exists(子查询)
语义:子查询结果中有无元组存在
示例:检索学过001号教师主讲的所有课程的所有同学的姓名
Select Sname From Student
Where not exists //不存在
————(Select * From Course //有一门001教师主讲课程
————Where Course.T#=’001‘ and not exists //该同学没学过
————————(Select * From SC
————————Where S#=Student.S# and C#=Course.C#));
上面语句的意思是:不存在有一门001号教师主讲的课程该同学没学过
3.6.4 利用SQL语言进行结果计算与聚集计算
1.结果计算: Select From Where语句中,Select 子句后面不仅可是列名,而且可是一些计算表达式或聚集函数,表明在投影的同时直接进行一些运算
————Select 列名 | expr|agfunc(列名) [[,列名|expr|agfunc(列名)]…]
————From 表名1[,表名2…]
————[Where 检索条件]
expr可以是常量,列名,或由常量,列名,特殊函数及算术运算符构成的算数运算式。特殊函数的使用需要结合各自DBMS的说明书
agfunc()是一些聚集函数
示例: 求有差额的任意两位教师的薪水差额
Select T1.Tname as TR1,T2.Tname as TR2,T1.Salary-T2.Salary
From Teacher T1,Teacher T2
Where T1.Salary > T2.Salary;
示例:依据学生年龄求出学生的出生年份,当前是2015年
Select S.S#,S.Sname,2015-S.Sage +1 as Syear
From Student S;
2.应用聚集函数进行统计计算
聚集函数: SQL提供了五个作用在简单列值集合上的内置聚集函数agfunc,分别是:COUNT,SUM,AVG,MAX,MIN
示例:求教师的工资总额
Select Sum(Salary) From Teacher;
示例:求数据库课程的平均成绩
Select AVG(Score) From Course C,SC
Where C.Cname=’数据库‘ and C.C#=SC.C#;
3.6.5 利用SQL语言进行分组查询与分组过滤
1.分组查询:SQL可以将检索到的元组按照某一条件进行分类,具有相同条件值的元组划到一个组或一个集合中,同时处理多个组或集合的聚集运算
基本语法:Select 列名 | expr|agfunc(列名) [[,列名|expr|agfunc(列名)]…]
————From 表名1[,表名2…]
————[Where 检索条件]
————[Group by 分组条件];
分组条件可以是:列名1,列名2…
示例:求每一个学生的平均成绩
Select S#,AVG(Score) From SC
Group by S#;
上述是按学号进行分组,学号相同为一组,即一位同学
示例:求每一门课程的平均成绩
Select C#,AVG(Score) From SC
Group by C#;
上述是按课号进行分组,课号相同为一组,即一门课程
聚集函数是不允许用于Where子句中的:Where子句是对每一元组进行条件过滤的,而不是对集合进行条件过滤
2.分组过滤: 若要对集合(即分组)进行条件过滤,即满足条件的集合/分组留下,不满足条件的集合/分组剔除
having子句,又称分组过滤子句。需要有Group by子句支持,换句话说,没有Group by子句,便不能有having子句
基本语法::Select 列名 | expr|agfunc(列名) [[,列名|expr|agfunc(列名)]…]
————From 表名1[,表名2…]
————[Where 检索条件]
————[Group by 分组条件 [Having 分组过滤条件]];
示例:求不及格课程超过两门的同学的学号
Select S# From SC
Where Score <60
Group by S# Having Count(*)>2;
示例:求有10人以上不及格的课程号
Select C# From SC
Where Score <60
Group by C# Having Count(*)<10;
3.having子句与where子句表达条件的区别
每一行都要检查满足与否的条件要用where子句表达;
每一分组检查满足与否的条件要用having子句表达;
3.6.6 利用SQL语言实现关系代数操作
SQL语言:并运算-UNION,交运算-INTERSECT,差运算-EXCEPT
基本语法形式:子查询{Union[ALL] | Intersect[ALL] | Except [ALL] 子查询}
通常情况下自动删除重复元组:不带ALL。若要保留重复元组,则要带ALL
假设子查询1的一个元组出现m次,子查询2的一个元组出现n次,则该元组在:
- 子查询1 Union ALL 子查询2,出现m+n次
- 子查询1 Intersect ALL 子查询2,出现min(m,n)次
- 子查询1 Except ALL 子查询2,出现max(0,m-n)次
并-交-差的处理
示例:求学过002号课的同学或学过003号课的同学学号
Select S# From SC Where C#=’002‘
UNION
Select S# From SC Where C#=’003‘;
——————————————————
Select S# From SC Where C#=’002‘
INTERSECT
Select S# From SC Where C#=’003‘;
示例: 假定所有学生都有选课,求没学过002号课程的学生学号
Select DISTINCT S# From SC
EXCEPT
Select S# From SC Where C#=’002‘;
2.空值的处理: 数据库中有了空值,会影响许多方面,如影响聚集函数运算的正确性,不能参与算术,比较或逻辑运算等。
在SQL标准中和许多现流行的DBMS中,空值被用一种特殊的符号Null来标记,使用特殊的空值检测函数来获得某列的值是否为空值。
空值检测:** is [not] null** ——检测指定列的值是否为空值
示例:找出年龄值为空的学生姓名
Select Sname From Student
Where Sage is null;
注意,不能写作Where Sage = null;空值是不能进行运算的。
现流行DBMS的空值处理小结:
- 除is [not] null之外,空值不满足任何查找条件
- 如果null参与算术运算,则该算术表达式的值为null
- 如果null参与比较运算,则结果可视为false。在SQL-92中可堪称unknown
- 如果null参与聚集运算,则除count(*)之外其他聚集函数都忽略null
3.内连接,外连接: 关系代数运算中,有连接运算,又分为
θ
\theta
θ连接和外连接,在标准SQL语言中连接运算通常是采用:
————————Select 列名 [[,列名]…]
————————From 表名1,表名2,…
————————Where 检索条件;
SQL的高级语法中引入了内连接与外连接运算,具体形式:
————————Select 列名 [[,列名]…]
————————From 表名1[NATURAL]
—————————[INNER | {LEFT|RIGHT|FULL } [OUTER]] JOIN 表名2
————————{ON 连接条件 | Using {Colname{,Colname…}}}
————————[Where 检索条件];
上例的连接运算由两部分构成:连接类型和连接条件
3.6.7 SQL语言之视图及其应用
1.SQL-视图的概念和结构
回顾:三级模式两层映像结构
——对应概念模式的数据在SQL中被称为基本表(Table),而对应外模式的数据被称为视图(View)。视图不仅包含外模式,而且包含其E-C映像。
SQL数据库结构:基本表是实际存储于存储文件中的表,基本表中的数据是需要存储的;视图在SQL中只存在其由基本表导出视图所需要的公式,即由基本表产生视图的影响信息,其数据并不存储,而是在运行过程中动态产生与维护的;对视图数据的更改最终要反应在对基本表的更改上。
2.SQL-视图的定义
视图需要“先定义,后使用”
定义视图:create view view_name[(列名[,列名]…)]
————————as 子查询 [with check option]
如果视图的属性名缺省,则默认为子查询结果中的属性名;也可以显式指明其所拥有的列名。
with check option指明当对视图进行insert,update,delete时,要检查进行insert/update/delete的元组是否满足视图定义中子查询中定义的条件表达式。
示例:定义一个视图CompStud为计算机系的学生,通过该视图可以将Student表中其他系的学生屏蔽掉
Create View CompStud AS
—————(Select * From Student
—————Where D# in (Select D# From Dept
————————————Where Dname=‘计算机’));
示例:定义一个视图Teach为教师任课的情况,把Teacher表中的个人隐私方面的信息,如工资等屏蔽掉,仅反应其教哪门课及其学分等
Create View Teach AS
————(Select T.Tname, C.Cname, Credit
————From Teacher T, Course C
————Where T.T# = C.T#);
3.SQL-视图的使用
使用视图: 定义好的视图,可以像Table一样,在SQL各种语句中使用
示例: 检索主讲数据库课程的教师姓名,我们可使用Teach
————Select T.Tname From Teach T
————Where T.Cname = ‘数据库’;
示例:检索计算机系的所有学生,我们可使用CompStud
————Select * From CompStud;
定义视图,有时可方便用户进行检索操作
4.SQL-视图的更新问题
SQL视图更新: 是比较复杂的问题,因视图不保存数据,对视图的更新最终要反映到对基本表的更新上,而有时,视图定义的映射不是可逆的。
上述带有聚集函数的,更新视图后,是不可更新基本表的;
上述例子中,虽然没有聚集函数,但视图中缺少S#,S#时Student的主键,因此也不能更新基本表;若加上主键,则可以更新基本表。
SQL-视图更新的可执行性:
- 如果视图的select目标列包含聚集函数,则不能更新
- 如果视图的select子句使用了unique或distinct,则不能更新
- 如果视图中包括了group by子句,则不能更新
- 如果视图中包括了算术表达式计算出来的列,则不能更新
- 如果视图是由单个表的列构成,但并没有包括主键,则不能更新
——————对于单一Table子集构成的视图,即如果视图是从单个基本表使用选择,投影操作导出的,并且包含了基本表的主键,则可以更新。
5.SQL-视图的撤销
已经定义的视图也可以撤销
撤销视图: Drop View view_name
示例:撤销视图Teach
————Drop View Teach;