您的位置:首页 > 数据库

数据库复习总结(未写完...)

2017-12-04 20:55 176 查看
是根据老师的ppt总结的

第一章 绪论

数据库领域的四位图灵奖得主

Charles W. Bachman(查尔斯 • 巴赫曼) 1973 主持设计与开发了最早的网状数据库管理系统IDS

Edgar F. Codd(埃德加 • 科德) 1981
提出了关系模型

James Gray(詹姆斯 • 格雷) 1998 解决保障数据的完整性、安全性、并行性,以及从故障恢复方面发挥了十分关键的作用

Michael Stonebraker (迈克尔.斯通布雷克) 2014创造了数据库系统一系列奠基性基本概念和实际技术

数据模型三要素

数据结构:记录间的组织形式

数据操纵:特定结构下的操纵功能

数据完整性约束:记录内部及记录间的限定。

数据模型的分类

层次模型

网状模型

关系模型

面向对象模型

层次模型

数据结构:树型

典型代表:IMS系统

优缺点:直观易理解,但插入和删除限制多,不方便对现实联系

网状模型

数据结构:网(有向图)

典型代表:DBTG系统

优缺点:直观描述现实世界的复杂联系,但数据库结构复杂,不利于用户掌握

关系模型

域:属性的取值范围

关系模式:对关系结构的描述

    关系名(属性1,属性2,...,属性n),例:学生(学号,姓名,性别,系)

关系应具有的六条性质:

列是同质的;

不同的列可以出自同一个域;

列序无关性;(调换列序无影响)

任意两个记录不能完全相同;(不会出现冗余的记录)

行序无关性;(调换行序无影响)

属性必须取原子值。(不可再分)

第二章 关系数据库

关系数据结构的特点:实体和联系都用关系(集合)这种单一的数据结构来实现。

关系操作的特点:
操作对象和操作结果都是集合

笛卡尔积的计算

给定域 name={王小明 ,李莉},sex={男、女}

则name×sex={ (王小明, 男),(王小明, 女),(李莉, 男),(李莉, 女)}

笛卡尔积的结果中有许多元组是无意义的,可以认为其中有意义的元组构成关系,为实际的二维表。

基本概念

候选码 (Candidate Key):能唯一标识元组的属性(组)。

主码 (Primary Key):多个候选码中选定一个作主码。

主属性 (Prime Attribute):候选码中的诸属性。

非主属性 (Non-Key Attribute):不出现在任何候选码中的属性。

例:

学生
学号姓名
15001蔡济民计算机
15002小明数统
15003小花物光
当无重名时

候选码是 学号,姓名

主属性是 学号,姓名

非主属性是 系

有时候会遇见这种情况,比如:

车牌号,车牌颜色合在一起构成一个候选码

这时候主码就是车牌号+车牌颜色

车牌号和车牌颜色都是主属性。

关系模式定义

R(U,D,dom(),F),简记为R(U)

R是关系名,U是属性集,D是关系的域,dom()属性到域上的映射关系,F函数依赖

关系的完整性约束:对关系的正确性和相容性的限定

完整性分类:

实体完整性

参照完整性

用户定义完整性

实体完整性:规则要求所有出现在候选码中的属性每个都不能为空。

参照完整性:若属性(或属性组)F是基本关系R的外码,它与基本关系S的主码Ks相对应(基本关系R和S不一定是不同的关系),则对于R中每个元组在F上的值必须为:

或者取空值(F的每个属性值均为空值)

或者等于S中某个元组的主码值

例如:

Cno

Cname

Ccredit

Cpno

c1

数据库

4

c5

c2

高等数学

2

c3

信息系统

4

c1

c5

数据结构

4

c7

c6

数据处理

2

c7

Pascal语言

4

c6

外码Cpno只能取:
(1)空值(NULL),表示该课程没有先修课

(2)非空值,这时该值必须是课程表中已有的课程号,而不能是一个不存在的课程号

用户定义完整性:如性别只能取“男”、“女”值,成绩必须在0~100分之间。通常由RDBMS的Check约束提供这类检查。

关系代数

并、交、差要求参与运算的两个关系必须具有相同的结构。

关系上的传统集合运算

并:R∪S = { t | t ∈ R∨t ∈S }

差:R – S = { t | t ∈ R∧t ∈S }

交:R∩S = { t | t ∈ R∧t ∈ S }

        R∩S = R – ( R – S )

广义笛卡尔积:R×S (其中R为k1行n列,S为k2行m列)

列:(n+m)列的元组的集合,元组的前n列是关系R的一个元组,后m列是关系S的一个元组,行:k1×k2个元组

例:

R
AB
a1b1
a2b1
S
AB
a1b1
a1b2
R×S
R.AR.BS.AS.B
a1b1a1b1
a1b1a1b1
a2b1a1b1
a2b1a1b2
???做笛卡尔积后会出现违反关系的任意两个记录不能完全相同的性质,就不是关系模型了么
选择(σ):σF(R) = {t | t∈R∧F(t)= '真'}

例:

Sno

Sname

Ssex

Sage

Sdept

95001

李勇



20

CS

95002

刘晨



19

IS

95003

王敏



18

MA

95004

张立



19

IS

σSsex = ‘女' (S)

Sno

Sname

Ssex

Sage

Sdept

95002

刘晨



19

IS

95003

王敏



18

MA

投影(π)
从R中选择出若干属性列组成新的关系

πA(R) = { t[A] | t ∈R }

如:

π Sno,Sname,Ssex (S)

Sno

Sname

Ssex

95001

李勇



95002

刘晨



95003

王敏



95004

张立



基础的关系查询举例:

查询信息系(IS系)全体学生 σSdept = 'IS' (Student)或 σ5 ='IS' (Student)

查询年龄小于20岁的学生σSage < '20' (Student)

连接:从两个关系的笛卡尔积中选取属性间满足一定条件的元组。连接操作是同时从行和列的角度进行运算

R

A

B

C

a1

b1

5<
1a779
/strong>

[b]a1

b2

6

a2

b3

8

a2

b4

12

S

B

E

b1

3

b2

7

b3

10

b3

2

b5

2

AR.BCS.BE
a1b15b27
a1b15b310
a1b26b27
a1b26b310
a2b38b310
等值连接:从关系R与S的广义笛卡尔积中选取A、B属性值相等的那些元组

自然连接(一种特殊的等值连接):两个关系中进行比较的分量必须是同名属性(组),在结果中必须把重复的属性列去掉

R

A

B

C

a1

b1

5

a1

b2

6

a2

b3

8

a2

b4

12

S

B

E

b1

3

b2

7

b3

10

b3

2

b5

2

A

R.B

C

S.B

E

a1

b1

5

b1

3

a1

b2

6

b2

7

a2

b3

8

b3

10

a2

b3

8

b3

2

R  S

A

B

C

E

a1

b1

5

3

a1

b2

6

7

a2

b3

8

10

a2

b3

8

2

自然连接的意义:将两个有关联的表合成为一张信息等价的表。

除运算

R÷S = { tr [X] | tr∈R 析取 Ytr [X] 包含 πY (S) }
,其中: Y tr [X] : tr [X]在R中的象集

这个除运算的定义一般不好看

先说象集,

B

C

D

b1

c2

d1

b2

c1

d1

b2

c3

d2

CD在b2上的象集是
C

D

c1

d1

c3

d2

然后除运算就是

关系代数运算综合举例

关系模式:

S (Sno, Sname, Ssex, Sage, Sdep)

C (Cno, Cname, Ccredit, Cpno)

SC (Sno, Cno, Grade)

查询选修了C2课程的学生学号和姓名。

或是

查询选修了C2或C4课程的学生学号。

查询选修了C2和C4课程的学生学号。

错误答案:

没有任何一条记录会在一个属性列取两个不同值

或者

中间空白部分是SC

重命名(p) :ρR1 ( R ):将关系R重命名为R1;ρS( B1,B2,…,Bn ) ( R( A1,A2, …, An ) ):将关系R重命名为S,同时将关系R中的属性名A1,A2, …, An重命名为B1,B2,…,Bn 。

查询每门课的先修课的先修课(课程)

箭头忽视,老师ppt上面的,有点懒,就没去掉

查询不学C2课的学生学号

错误答案:

原因:如果该学生选c2课外还选了别的课,则非c2课的记录是符合条件的,此时会将该记录的学号置入结果集。

解决方法:先求出所有选c2课的学生,再从全体学生集合中减去这些学生。

查询选修全部课程的学生学号。

查询选修学号为“95002”的学生所选全部课程的学生学号和姓名。

总结:需要掌握的是4个传统的集合运算,交,并,差,笛卡尔积。5个专门的关系运算,选择,投影,连接,除,重命名。

关系代数表达式应该建立在关系模式上,而不是在某一特定的关系实例上满足。

第三章 关系数据库标准语言SQL

SQL的功能

数据查询 SELECT

数据定义 CREATE,DROP,ALTER

数据操纵 INSERT,UPDATE,DELETE

数据控制GRANT,REVOKE,COMMIT,ROLLBACK

SQL与三级模式体系结构

内模式,模式和外模式,其中视图属于外模式,存储文件属于内模式,基本表属于模式。

create table stu

(

name char(8);

sno int primary key;

);

常用完整性约束

(1) 主码约束: PRIMARY  KEY

(2) 唯一性约束:UNIQUE(不能取相同值但允许多个空值)

(3) 非空值约束:NOT NULL

(4) 参照完整性约束:

 FOREIGN KEY (<列名>) REFERENCES <表名>(<列名>)

(5) CHECK约束:CHECK ( <谓词>)

(6) 断言(Assertion)约束 

主码的三种指定方式

1) 用NOT NULL  UNIQUE 作为列级约束指定

2) 用PRIMARY KEY 作为列级约束指定

3) 用PRIMARY  KEY  (<主码>) 作为表级约束指定DROP  TABLE <表名> ; 

DROP TABLE  Student ;

基本表删除后,表里的数据、表上的索引都会被删除,表上的视图往往仍然保留,但无法引用。

删除基本表时,系统会从数据字典中删去有关该基本表及其索引的描述。 

ALTER TABLE <表名>

[ ADD  <新列名>  <数据类型>  [ 完整性约束 ] ]

[ DROP  <完整性约束名>  <列名>]

[ ALTER  <列名> <数据类型> ];

<表名>:要修改的基本表

ADD子句:增加新列和新的完整性约束条件

DROP子句:删除指定的完整性约束条件

ALTER子句:用于修改列名和数据类型ALTER TABLE <表名>

例:

ALTER  TABLE  Student  ADD  Senroll  DATE ;

ALTER  TABLE  Student  ALTER  Sage  SMALLINT ;

ALTER  TABLE  Student  DROP  UNIQUE(Sname) ;

删除属性列分为直接删除(SQL-99)和间接删除

ALTER  TABLE  Student  Drop  Senroll ;

索引

分为三类,单一索引聚蔟索引普通索引 

Search-key项常用的组织方式是顺序或Hash排列。

单一索引(Unique Index):每一个索引值只对应唯一的数据记录。

聚簇索引(Cluster Index):索引项顺序与表中数据记录的物理顺序一致。

普通索引:允许一个Search-key项对应多条存储记录。

CLUSTER:表示要建立的索引是聚簇索引

CREATE [UNIQUE] [CLUSTER] INDEX <索引名>  ON  <表名>(<列名>[<次序>][,<列名>[<次序>] ]…) ;

例:为学生-课程数据库中的Student,Course,SC三个表建立索引。其中Student表按学号升序建唯一索引,Course表按课程号升序建唯一索引,SC表按学号升序和课程号降序建唯一索引。

CREATE  UNIQUE  INDEX  Stusno  ON  Student(Sno) ;
CREATE  UNIQUE  INDEX  Coucno  ON  Course(Cno) ;
CREATE  UNIQUE  INDEX  SCno  

  ON  SC(Sno  ASC , Cno  DESC) ;

删除Student表的Stusname索引。

DROP  INDEX  Stusname ;

SQL标准中没有定义对索引的修改功能,而采用删除后重新定义索引的方式实现。

数据查询

SELECT  [ ALL | DISTINCT ] <目标列表达式1> [, <目标列表达式2>] …

FROM  <表名或视图名1>[,  <表名或视图名2> ] …

[ WHERE  <条件表达式> ]

[ GROUP BY  <列名1> [ HAVING <条件表达式> ] ]

[ ORDER BY  <列名2> [ ASC | DESC ] ] ;

相关子句的说明:

SELECT子句:指定要显示的属性

FROM子句:指定查询对象(基本表或视图)

WHERE子句:指定查询条件

GROUP BY子句:对查询结果按指定列分组,列值相同的记录为一组,通常再在该组上施加集函数运算

HAVING短语:筛选出只有满足指定条件的组

ORDER BY子句:对查询结果按指定列值升序或降序排序

1)目标列(SELECT子句)为表达式的查询

查全体学生的姓名及其出生年份。
SELECT  Sname, 1996 - Sage

FROM  Student ;

2)使用列别名改变查询结果的列标题

[例5.1]  查询全体学生的姓名、出生年份和所在系,在“出生年份”前加入常数列“Year of Birth:”,用小写字母表示所有系名,并将输出字段依次更名为:NAME、BIRTH、BIRTHYEAR、DEPARTMENT。
SELECT  Sname  NAME, 'Year of Birth:'  BIRTH,
     1996 - Sage  BIRTHYEAR, 
     ISLOWER ( Sdept )  DEPARTMENT

FROM  Student ;

3)消除结果中取值重复的行

  —— 在SELECT子句中使用DISTINCT短语。

2)确定范围

[例10]  查询年龄在20~23岁(包括20岁和23岁)之间的学生的姓名、系别和年龄。
SELECT  Sname , Sdept , Sage

FROM  Student

WHERE  Sage  BETWEEN  20  AND  23 ;

3)确定集合

[例13]  查询不是信息系(IS)、数学系(MA)和计算机科学系(CS)学生的姓名和性别。
 SELECT  Sname , Ssex

FROM  Student

WHERE  Sdept  NOT  IN ( 'IS', 'MA', 'CS' ) ;

4)字符串匹配
 [NOT] LIKE  ‘<匹配模板>’  [ESCAPE ‘<换码字符>’]

匹配模板:固定字符串或含通配符的字符串。

通配符:

% (百分号):代表任意长度(可以为0)的字符串。
  例:a%b表示以a开头,以b结尾的任意长度的字符串。如acb,addgb,ab 等都满足该匹配串。

_ (下横线):代表任意单个字符。
  例:a_b表示以a开头,以b结尾的长度为3的任意字符串。如acb,afb等都满足该匹配串

当要查询的字符串本身就含有 % 或 _ 时,要使用ESCAPE '<换码字符>' 短语对通配符进行转义。

匹配模板为含通配符的字符串

[例15]  查询所有姓刘学生的姓名、学号和性别。

      SELECT  Sname , Sno , Ssex

FROM  Student

WHERE  Sname  LIKE  '刘%' ;

[例17]  查询姓名中第3个字为"阳"字的学生姓名和学号。

      SELECT  Sname , Sno

FROM  Student

WHERE  Sname  LIKE  '_ _ _ _阳%' ;

5)涉及空值的查询

使用谓词 IS NULL 或 IS NOT NULL

 “IS NULL” 不能用 “= NULL” 代替!

[例21]  某些学生选修课程后没有参加考试,所以有选课记录,但没有考试成绩。查询缺少成绩的学生的学号和相应的课程号。
SELECT  Sno , Cno

FROM  SC

WHERE  Grade  IS  NULL ;

三、对查询结果排序输出

—— 使用ORDER BY子句

可以按一个或多个属性列排序

升序:ASC;

降序:DESC;

缺省值为升序

当排序列含空值时

ASC:排序列为空值的元组最后显示

DESC:排序列为空值的元组最先显示

(将空值作为最大值来理解)

use Stu_course_mng

select *

from Student

order by Sno DESC

自身连接

SELECT  FIRST.Cno, SECOND.Cpno

FROM  Course  FIRST, Course  SECOND

WHERE  FIRST.Cpno = SECOND.Cno ; 

注:

(1) 一个表与其自己进行连接,称为表的自身连接

(2) 需要给表起别名以示区别

(3) 由于所有属性名都是同名属性,因此必须使用别名前缀

外连接(join跳过,很少用)

四、使用集函数(Aggregate Functions,聚集函数)

(1) 计数

COUNT([DISTINCT | ALL] *)

COUNT([DISTINCT | ALL] <列名>)

(2) 计算总和

SUM([DISTINCT | ALL] <列名>)

(3) 计算平均值

AVG([DISTINCT | ALL] <列名>)

(4) 求最大值

MAX([DISTINCT | ALL] <列名>)

(5) 求最小值

MIN([DISTINCT | ALL] <列名>)

查询选修c1号课程的学生最高分数。

      SELECT MAX (Grade)

FROM  SC

WHER  Cno = 'c1' ;

五、对查询结果分组输出

—— 使用GROUP BY子句分组

语法:[ GROUP BY  <列名1>[, 列名2…] [ HAVING <条件表达式> ] ] 

作用:细化集函数的作用对象

分组方法:按指定的一列或多列分组,值相等为一组

HAVING子句作用于且只能作用于各组之上

GROUP BY子句的作用对象是查询的中间结果表

未对查询结果分组,集函数将作用于整个查询结果

对查询结果分组后,集函数将分别作用于每个组 

使用GROUP BY子句后,SELECT子句的列名表中只能出现分组属性和集函数

求各个课程号及相应的选课人数。
SELECT  Cno , COUNT(Sno)

FROM  SC

GROUP  BY  Cno ;

查询有3门以上课程是90分以上的学生学号及其(90分以上的)课程数。
 SELECT  Sno , COUNT(*)

FROM  SC

WHERE  Grade >= 90
GROUP  BY  Sno
HAVING  COUNT(*) >= 3 ;

[例37]  查询与“刘晨”在同一个系学习的学生。
此查询要求可以分步来完成

① 确定“刘晨”所在系名             
SELECT  Sdept  

FROM  Student                            

WHERE  Sname = '刘晨' ;

② 查找所有所在系与上一步查询结果相等的学生。    
SELECT  Sno, Sname, Sdept

FROM  Student

WHERE  Sdept =(

SELECT  Sdept  

FROM  Student                            

WHERE  Sname = '刘晨' ;

)

执行过程:
(1) 先执行子查询,得到结果集
(2) 再执行父查询WHERE  Sdept  =  {上一步查询结果}

这种查询称为不相关子查询,即子查询的执行不依赖于父查询的条件。

采用不相关子查询的效率要优于连接查询。

返回单值时可以用 = 代替IN

三、带有ANY或ALL谓词的子查询

谓词语义:

(1) ANY ( SOME ):某些值; (2)  ALL:所有值

需要配合使用比较运算符:

> ANY 大于子查询结果中的某个值       

> ALL 大于子查询结果中的所有值

< ANY 小于子查询结果中的某个值    

< ALL 小于子查询结果中的所有值

>= ANY 大于等于子查询结果中的某个值    

>= ALL 大于等于子查询结果中的所有值

<= ANY 小于等于子查询结果中的某个值    

<= ALL 小于等于子查询结果中的所有值

= ANY 等于子查询结果中的某个值        

=ALL 等于子查询结果中的所有值(通常没有实际意义)

!=(或<>) ANY    不等于子查询结果中的某个值

!=(或<>) ALL    不等于子查询结果中的任何一个值

[例39]  查询其他系中比信息系某些学生年龄小的学生姓名和年龄。

      SELECT  Sname, Sage

FROM  Student

WHERE  Sage < ANY ( SELECT  Sage

                                          FROM  Student

                                          WHERE  Sdept = 'IS' )
    AND  Sdept <> 'IS' ;   //这是父查询块中的条件

执行过程

1. DBMS执行此查询时,首先处理子查询,找出IS系中所有学生的年龄,构成一个集合(19,18) ;

2. 处理父查询,找所有不是IS系且年龄小于19 或 18的学生。

结论:是不相关子查询

 执行效率比较:
用集函数实现子查询通常比直接用ANY或ALL查询效率要高,因为前者通常能够减少比较次数。

EXISTS谓词的意义:

是存在量词  在SQL中的应用;

带有EXISTS谓词的子查询不返回任何数据,只产生逻辑真值“True”或逻辑假值“False” ;

若内层查询结果非空,则返回真值

若内层查询结果为空,则返回假值

由EXISTS引出的子查询,其目标列表达式通常都用 * 。

因为带EXISTS的子查询只返回真值或假值,给出列名无实际意义。

查询所有选修了c1号课程的学生姓名。

SELECT  Sname

FROM  Student

WHERE  EXISTS
( SELECT    *

     FROM  SC 
 WHERE  Sno = Student.Sno  AND  Cno = 'c1' ) ;

输出那些学生的姓名,当在选课表中存在他(她)选修c1号课的记录。

(1)首先取外层查询中表的第一个元组,根据它与内层查询相关的属性值处理内层查询,若WHERE子句返回值为真,则取此元组放入结果表;

(2)然后再取外层表的下一个元组,重复这一过程,直至外层表全部检查完为止。
  此类查询称为相关子查询,即子查询的条件与父查询当前值相关。

 使用EXISTS子查询的效率要优于连接查询。

查询没有选修c1号课程的学生姓名。

SELECT  Sname

FROM  Student

WHERE  NOT  EXISTS

( SELECT  *

               FROM  SC

               WHERE  Sno=Student.Sno  AND  Cno = 'c1' ) ;

注:此查询为相关子查询,此例用连接查询无法实现!

关于EXISTS子查询的说明:

一些带EXISTS或NOT EXISTS谓词的子查询不能被其它形式的子查询等价替换。

所有带IN谓词、比较运算符、ANY和ALL谓词的子查询都能用带EXISTS谓词的子查询等价替换。

[NOT] EXISTS子查询的效率要优于连接查询和集合查询(IN谓词查询)。

查询至少选修学生95002所选全部课程的学生学号。

等价转换后的自然语义:
输出这样的学生,不存'95002'选了的课程,在他的选课记录中没有出现。
SQL语句:
SELECT   Sno

FROM  SC  SCX

WHERE  NOT  EXISTS
( SELECT  *
 FROM  SC  SCY
 WHERE  SCY.Sno = '95002'  AND  NOT  EXISTS
 ( SELECT  *
   FROM  SC  SCZ
   WHERE  SCZ.Sno = SCX.Sno AND
       SCZ.Cno = SCY.Cno )) ;

集合查询
—— 将两个SELECT – FROM – WHERE查询块用集合操作语句联结起来。

集合操作命令:

并操作(UNION)

交操作(INTERSECT)

差操作(MINUS, SQL Server 中用EXCEPT)

语句形式

<查询块>

UNION

<查询块> ;

注:参加UNION操作的各结果表的列数必须相同;对应项的数据类型也必须相同。

查询计算机系年龄不大于19岁的学生学号。
方法一:

      SELECT  Sno

FROM  Student

WHERE  Sdept = 'CS'  AND  Sage <= 19 ;

方法二:

      SELECT  Sno

FROM  Student

WHERE  Stept = 'CS'

      MINUS

      SELECT  Sno

FROM  Student

WHERE  Sage > 19 ;

查询效率:使用集合操作能更好地利用索引,效率高。

MINUS大概就是交集的意思,具体是这样的
minus指令是运用在两个 SQL 语句上。它先找出第一个 SQL 语句所产生的结果,然后看这些结果有没有在第二个 SQL
语句的结果中。如果有的话,那这一笔资料就被去除,而不会在最后的结果中出现。如果第二个 SQL 语句所产生的结果并没有存在于第一个 SQL 语句所产生的结果内,那这笔资料就被抛弃。
MINUS 的语法如下:
[SQL 语句 1]
MINUS
[SQL 语句 2]

查询注意事项:
一、别名的使用
(1) 别名用于对输出属性列的重命名

(2) 别名用于自身连接查询和对同一表的相关子查询中,用于区别对同一表的不同引用

(3) 对不相关子查询可以不使用别名

二、distinct的使用
—— DISTINCT用于区分相同的记录,将多条相同的记录作为一条处理。

三、集函数的使用
——集函数只能用于 SELECT子句和 HAVING短语之中,而绝对不能出现在 WHERE子句中(WHERE子句执行过程是对记录逐一检验,并没有结果集,故无法施加集函数)。  
错误例子:

例:查询年龄最大的学生。

      SELECT  *

FROM  Student

WHERE  Sage = MAX (Sage) ;

正确的查询语句:

      SELECT  *

FROM  Student

WHERE  Sage = ( SELECT  MAX (Sage) 
       FROM  Student ) ;
错误例子:
例:查询平均成绩最高的学生学号。
 SELECT  Sno

FROM  SC

GROUP  BY  Sno

HAVING  AVG(Grade) =
( SELECT MAX (AVG(Grade))
 FROM  SC
 GROUP  BY  Sno ) ;

注:集函数没有复合功能,换成下部分:

  HAVING  AVG(Grade) >= ALL 
( SELECT  AVG(Grade)
 FROM  SC
 GROUP  BY  Sno ) ;

四、ESIST与IN
——EXISTS通常引入的是相关子查询,而IN更多的是不相关子查询

[例] 查询所有没有选修了c1号课程的学生姓名。

(法一) SELECT  Sname
  FROM  Student
  WHERE  Sno NOT IN
( SELECT  Sno

     FROM  SC 
 WHERE  Cno = 'c1' ) ;

错误方法:
(法二) SELECT  Sname
  FROM  Student
  WHERE  NOT EXISTS
( SELECT  *

      FROM  SC 
  使用了分组的查询语句,其SELECT子句中只能出现分组属性和集函数,而不能有在GROUP  BY没有出现的属性。
  原因在于SELECT子句是对分组后的结果集进行输出,参与分组的属性在同一组中取相同值,而不参与分组的属性(不在GROUP  BY子句中出现的属性)则可能取不同的值,分组输出通常是对组的整体描述,而不是组内的详细记录,不参与分组的属性取值不同,故无法输出。

例:查询各系的学生人数。

      SELECT  Sdept, Ssex, COUNT(*)

FROM  Student

GROUP  BY  Sdep ;
  WHERE  Cno = 'c1' ) ;

将最后一句的WHERE改为这个就对了
WHERE Sno = Student.Sno  AND  Cno = 'c1' ) ;

五、GROUP BY的使用
GROUP  BY子句在复合查询中的应用
GROUP BY子句用来对查询结果进行分组,通常用作对各组的统计,可用于子查询。

[例50]  查询平均成绩“优秀”(>=90分)的学生学号和姓名,并按学号升序输出。
SELECT  Sno, Sname

FROM  Student

WHERE  Sno  IN

      ( SELECT  Sno
        FROM  SC
        GROUP  BY  Sno
     HAVING  AVG(Grade) >= 90 )

ORDER  BY  Sno  ASC ;

使用了分组的查询语句,其SELECT子句中只能出现分组属性和集函数,而不能有在GROUP  BY没有出现的属性。
原因在于SELECT子句是对分组后的结果集进行输出,参与分组的属性在同一组中取相同值,而不参与分组的属性(不在GROUP  BY子句中出现的属性)则可能取不同的值,分组输出通常是对组的整体描述,而不是组内的详细记录,不参与分组的属性取值不同,故无法输出。

例:查询各系的学生人数。

      SELECT  Sdept, Ssex, COUNT(*)

FROM  Student

GROUP  BY  Sdep ;

原因在于组内的性别值不同,输出值无法确定。

我敲了敲,这段的意思是这样的
use SPJ_mng

select SNO,STATUS1,count(*)

from S
group by SNO,STATUS1

SNO
STATUS1 无列名
1
S1   20
1

2 S2  
10 1

3 S3  
30 1

4 S4  
20 1

5 S5  
30 1

如果没有STATUS1,在最后的group by里面会报错,消息 8120,级别 16,状态 1,第 2 行

选择列表中的列 'S.STATUS1' 无效,因为该列没有包含在聚合函数或 GROUP BY 子句中。
就相当于你分了两组统计了,但是并没有分两组输出

六、Order by的使用
ORDER  BY子句用于对查询结果进行排序后再输出,故只用于最外层的查询,而子查询中不应该出现ORDER BY子句。排序属性必须是SELECT子句中出现的属性。

查询学习“数据库”课程的学生学号和成绩,并按成绩由高到低进行排序。
SELECT  Sno, Grade

FROM  SC

WHERE  Cno = ( SELECT  Cno
      FROM  Course
      WHERE  Cname = '数据库' )

ORDER  BY  Grade  DESC ; 
例:查询全体学生的学号和平均成绩,并按平均成绩降序输出。

      SELECT  Sno, AVG(grade)

FROM  SC

GROUP  BY  Sno

OREDER  BY AVG(grade)  DESC;
注:ORDER  BY子句中允许出现集函数,但不具有集函数的运算功能,仅代表输出缓冲区中的列。
 也可以在SELECT子句中对集函数列进行重命名后,在ORDER BY子句中使用别名。

查询计算机系年龄不大于19岁的学生信息,并按学号升序输出。

错误答案:
      SELECT  *

FROM  Student

WHERE  Sdept = 'CS'

ORDER  BY Sno

INTERSECT

SELECT  *

FROM  Student

WHERE  Sage <= 19

ORDER  BY  Sno ;

中间多了一个ORDER BY SNO
因为Order by只用于最外层的查询排序

七、输出多个表的属性的查询
  查询的输出只能取自最外层查询所使用的表,对于子查询中的属性是不能作为最终的输出的。如果输出的属性涉及多个表,则最外层查询只能使用连接查询。 

例:查询成绩超过80分的学生学号、姓名、课程号和成绩。
错误答案:
  SELECT  DISTINCT  Sno, Sname, Cno, Grade

  FROM  Student

  WHERE  Sno  IN ( SELECT  Sno
         FROM  SC
     WHERE  Grade >= 80 ) ;

  正确的查询语句:

        SELECT  Sno, Sname, Cno, Grade

  FROM  Student, SC

  WHERE  Student.Sno = SC.Sno  AND  Grade >= 80 ;

八、导出关系作为数据源的使用
子查询的结果集可以看作基本关系一样作为查询的数据源,需要对结果集命名别名以便引用。

例:查询全体学生的学号、姓名和平均成绩。

      SELECT  Sno, Sname, avg_grade

FROM  Student, ( SELECT  Sno, AVG(Grade)  AS 
   avg_grade
      FROM  SC
    GROUP  BY  Sno )  AS  SC_AVG

WHERE  Student.Sno = SC_AVG.Sno ;

九、SQL性能优化拾遗(应该跟考试无关吧)
第一个原则:在WHERE子句中应把最具限制性的条件放在最前面

例:

(1) SELECT  *

FROM  table1

WHERE  field1 <= 10000  AND  field1 >= 0 ;

(2) SELECT  *

FROM  table1

WHERE  field1 >= 0  AND  field1 <= 10000 ;    

    如果数据表中数据的 field1 值大部分都>=0,则语句(1) 要比语句(2) 效率高得多,因为语句(2)的第一个条件耗费了大量的系统资源。

第二个原则: WHERE子句中字段的顺序应和索引中字段顺序一致

例:
SELECT  *

FROM  tab

WHERE  a =…  AND  b =…  AND  c =… ;
  若有索引INDEX(a,b,c),则WHERE子句中字段的顺序应和索引中字段顺序一致。

数据更新
一、插入数据
(1) 插入单个元组 —— 新元组插入指定表中。
  语句格式:
INSERT
INTO  <表名>  [(<属性列1>[, <属性列2 >…)]
VALUES  (<常量1> [, <常量2>]    … ) ;

注:

INTO子句

指定要插入数据的表名及属性列

属性列的顺序可与表定义中的顺序不一致

没有指定属性列:表示要插入的是一条完整的元组,且属性列属性与表定义中的顺序一致

指定部分属性列:插入的元组在其余属性列上取空值

VALUES子句

 提供的值的个数和值的类型必须与INTO子句匹配

将一个新学生记录 ( 学号:95020;姓名:陈冬;性别:男;所在系:IS;年龄:18岁 ) 插入到Student表中。
INSERT

INTO  Student

VALUES   ( '95020' , '陈冬' , '男' , 'IS' , 18) ; 

插入一条选课记录( '95020', '1' )。
INSERT

INTO   SC ( Sno, Cno )

VALUES  ( '95020' ,'1' ) ;
注:新插入的记录在Grade列上取空值。

??? 问题:若待插入记录未指定值的列在表上是NOT NULL约束会如何?
二、修改数据
语句格式:

UPDATE  <表名>

SET  <列名>=<表达式>[, <列名>=<表达式>]…

[WHERE  <条件>] ;

功能:

修改指定表中满足WHERE子句条件的元组。

注:

SET子句 —— 指定修改方式,要修改的列和修改后取值

WHERE子句

指定要修改的元组

缺省表示要修改表中的所有元组

(1) 用WHERE子句指定修改单个记录

[例4]  将学生95001的年龄改为22岁。
UPDATE  Student

SET  Sage = 22

WHERE  Sno = '95001' ;

(2) 用WHERE子句(或不用)指定修改多个记录

[例5]  将所有学生的年龄增加1岁。
 UPDATE  Student

SET  Sage = Sage+1 ;

[例6]  将信息系所有学生的年龄增加1岁。
 UPDATE  Student

SET  Sage = Sage+1

WHERE  Sdept = 'IS' ;

(3) 用子查询指定要修改的记录
错误答案:

[例7]  将计算机科学系全体学生的成绩置零。
 UPDATE  SC

SET  Grade = 0

WHERE  ( SELECT  Sdept
      FROM  Student
      WHERE  Student.Sno = SC.Sno ) = 'CS' ;

正确的语句:
UPDATE  SC

SET  Grade = 0

WHERE  'CS'=
      ( SELECT  Sdept

               FROM  Student

               WHERE  Student.Sno = SC.Sno ) ;

这个是不能放在后面就是匹配的字符串
三、删除数据
语句格式:

DELETE

FROM  <表名>

[WHERE  <条件>] ;

功能

删除指定表中满足WHERE子句条件的元组

注:

WHERE子句

指定要删除的元组

缺省表示要修改表中的所有元组

???delete 通常是删除单条或多条记录,drop是删除一个表
(3) 用子查询指定要删除的记录

[例11]  删除计算机科学系所有学生的选课记录。

      DELETE

FROM  SC

WHERE  Sno  IN ( SELECT  Sno
        FROM  Student
        WHERE  Student.Sdep = 'CS' ) ;

  或
DELETE

FROM  SC

      WHERE  'CS' =

             ( SELECT  Sdept

             FROM  Student

                      WHERE  Student.Sno = SC.Sno ) ; 

删除数据有时候会破坏完整性规则
第一种是不允许删除,第二种是级联删除
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: