例题所使用的表如下:
Create Table student(
Sno char(12) Primary Key,
Sname char(12),
Ssex char(2),
Sdept char(40),
Sage SmallInt
);
Insert Into Student Values ('20191102062','刘哲轩','男','Computer Science',19)
Insert Into Student Values ('20191102063','叶晓晓','男','information security',20)
Insert Into Student Values ('20191102064','刘小轩','女','Computer Science',21)
Insert Into Student Values ('20191102065','叶大大','男','information security',20)
Insert Into Student Values ('20191102066','刘大轩','男','Computer Science',22)
Insert Into Student Values ('20191102067','刘轩','女','information security',20)
Insert Into Student Values ('20191102068','刘车干','男','Computer Science',19)
Insert Into Student Values ('20191102069','刘刘','女','information security',20)
Insert Into Student Values ('20191102070','刘刘流','男','Computer Science',22)
Insert Into Student Values ('20191102071','叶小刘','女','information security',20)
Create Table Course(
Cno Char(12) Primary Key,--课序号
Cname Char(12),
Cpno Char(12),--先行课的课序号
Ccredit SmallInt,
Foreign Key(Cpno) References Course(Cno)
);
Insert Into Course Values('1','数据库',null,4)
Insert Into Course Values('2','数学',null,2)
Insert Into Course Values('3','信息系统',null,4)
Insert Into Course Values('4','操作系统',null,3)
Insert Into Course Values('5','数据结构',null,4)
Insert Into Course Values('6','数据处理',null,2)
Insert Into Course Values('7','PASCAL语言',null,4)
update course set cpno='5' where cno='1'
update course set cpno='1' where cno='3'
update course set cpno='6' where cno='4'
update course set cpno='7' where cno='5'
update course set cpno='6'where cno='7'
Create Table SC(--学生选课表
Sno Char(12),
Cno Char(12),
Grade SmallInt,
Primary Key(Sno, Cno),
Foreign Key(Sno) References Student(Sno),
Foreign Key(Cno) References Course(Cno)
);
Insert Into SC Values('20191102062', '1', 100)
Insert Into SC Values('20191102062', '2', 51)
Insert Into SC Values('20191102063', '1', 65)
Insert Into SC Values('20191102064', '2', 46)
Insert Into SC Values('20191102065', '3', 85)
Insert Into SC Values('20191102066', '3', 95)
Insert Into SC Values('20191102067', '7', 99)
Insert Into SC Values('20191102068', '6', 93)
在SQL语言中,一个 SELECT-FROM-WHERE 语句称为一个查询块。将一个查询块嵌套在另一个查询块的WHERE子句或HAVING短语的条件中的查询称为嵌套查询(nestedquery)。例如:
Select Sname From Student Where Sno In
(Select Sno From SC Where Cno = '2')
执行结果如下:
在嵌套查询中,子查询的结果往往是一个集合,所以谓词IN是嵌套查询中最经常使用的谓词。
Select Sno, Sname, Sdept
From Student Where Sdept In(
Select Sdept From Student
Where Sname = '刘哲轩'
)
结果如下:
本例中,子查询的查询条件不依赖于父查询,称为不相关子查询。一种求解方法是由里向外处理,即先执行子查询,子查询的结果用于建立其父查询的查找条件.
本查询涉及学号、姓名和课程名三个属性。学号和姓名存放在:Student表中,课程名存放在Course表中,但 Student与 Course两个表之间没有直接联系,必须通过SC 表建立它们二者之间的联系。所以本查询实际上涉及三个关系。
Select Sno, Sname From Student
Where Sno In(
Select Sno From SC
Where Cno In(
Select Cno From Course
Where Cname = '信息系统'
)
)
查询结果如下:
例3.55和例3.56中子查询的查询条件不依赖于父查询,这类子查询称为不相关子查询。不相关子查询是较简单的一类子查询。如果子查询的查询条件依赖于父查询,这类子查询称为相关子查询(correlated subquery),整个查询语句称为相关嵌套查询(correlatednested query)语句。
带有比较运算符的子查询是指父查询与子查询之间用比较运算符进行连接。当用户能确切知道内层查询返回的是单个值时,可以用>、<、=、>=、<=、=或<>等比较运算符。
Select Sno, Cno
From SC x
Where Grade >= (Select AVG(Grade) From SC y Where y.Sno=x.Sno)
结果如下:
x是表SC的别名,又称为元组变量,可以用来表示SC的一个元组。内层查询是求一个学生所有选修课程平均成绩的,至于是哪个学生的平均成绩要看参数x.Sno的值,而该值是与父查询相关的,因此这类查询称为相关子查询。
Any 和All与各类比较运算符组合的效果如下:
Select Sname, Sage
From Student Where Sage < Any(Select Sage From Student
Where Sdept='Computer Science'
)
And Sdept <> 'Computer Science'
结果如下:
SELECT Sname,Sage FROM Student
WHERE Sage<ALL
(SELECT Sage FROM Student
WHERE Sdept = 'Computer Science')
AND Sdept <> 'Computer Science';
本查询同样也可以用聚集函数实现。
Select Sname, Sage From
Student Where Sage < (
Select Min(Sage) From Student
Where Sdept = 'Computer Science'
)
And Sdept <> 'Computer Science'
事实上,用聚集函数实现子查询通常比直接用ANY 或ALL查询效率要高
Any与All的对应聚集函数的关系如下:
EXISTS 代表存在量词 ? \exist ?:。带有EXISTS谓词的子查询不返回任何数据,只产生逻辑真值“true”或逻辑假值“false”。
本查询涉及Student 和SC表。可以在Student 中依次取每个元组的Sno 值,用此值去检查SC表。若SC中存在这样的元组,其Sno值等于此Student.Sno值,并且其Cno=‘1’,则取此Student.Sname送入结果表。将此想法写成SQL语句是:
Select Sname From Student
Where Exists(
Select * From SC
Where Sno=Student.Sno And Cno='1');
结果如下:
使用存在量词EXISTS后,若内层查询结果非空,则外层的WHERE子句返回真值,否则返回假值。
本例中子查询的查询条件依赖于外层父查询的某个属性值(Student 的 Sno值),因此也是相关子查询。
使用存在量词NOT EXISTS后,若内层查询结果为空,则外层的 WHERE子句返回真值,否则返回假值。
Select Sname From Student
Where Not Exists(
Select * From SC
Where Sno = Student.Sno And Cno = '1'
)
运行结果如下:
由于带EXISTS量词的相关子查询只关心内层查询是否有返回值,并不需要查具体值,因此其效率并不一定低于不相关子查询,有时是高效的方法。
SQL中没有全称量词(for all),但是可以把带有全称量词的谓词转换为等价的带有存在量词的谓词:
(
?
x
)
P
≡
?
(
(
?
x
)
(
?
P
)
)
(\forall x)P\equiv \neg ((\exist x)(\neg P))
(?x)P≡?((?x)(?P))
SQL语句如下:
Select Sname From Student
Where Not Exists (
Select * From Course
Where Not Exists(
Select * From SC
Where Sno = Student.Sno
And Cno = Course.Cno
)
);
书上的证明如下:
本查询可以用逻辑蕴涵来表达:查询学号为x的学生,对所有的课程y,只要201215122学生选修了课程y,则x也选修了y。形式化表示如下:
用p表示谓词“学生201215122选修了课程y”
(
?
y
)
p
→
q
(\forall y)p \rightarrow q
(?y)p→q
用q表示谓词“学生x选修了课程y”就学以虑贤淡本则上述查询为
p
→
q
≡
?
p
∨
q
p \rightarrow q \equiv \neg p \lor q
p→q≡?p∨q
该查询可以转换为如下等价形式:
(
?
y
)
p
→
q
(\forall y)p \rightarrow q
(?y)p→q
≡
\equiv
≡
?
\neg
?
?
\exist
?
y
(
p
∧
?
q
)
y(p\land \neg q)
y(p∧?q)
它所表达的语义为:不存在这样的课程y,学生201215122选修了y,而学生x没有选。用SQL 语言表示如下:
Select Distinct Sno
From SC SCX Where Not Exists (
Select * From SC SCY
Where SCY.Sno = '20191102062' And
Not Exists(
Select * From
SC SCZ Where SCZ.Sno=SCX.Sno And
SCZ.Cno=SCY.Cno
)
)
运行结果如下:
这是因为本表中没有选修了’20191102062’所选修的全部课程的人,hhh.
SELECT 语句的查询结果是元组的集合,所以多个SELECT 语句的结果可进行集合操作。集合操作主要包括并操作 UNION、交操作 INTERSECT 和差操作 EXCEPT。
Select * From Student
Where Sdept = 'Computer Science'
Union Select * From Student Where Sage <= 19;
结果如下:
本查询实际上是求计算机科学系的所有学生与年龄不大于19 岁的学生的并集。使用UNION将多个查询结果合并起来时,系统会自动去掉重复元组。如果要保留重复元组则用UNION ALL 操作符。
Select Sno From SC Where Cno = '1'
Union
Select Sno From SC Where Cno = '2'
结果如下:
Select Sno From Student Where Sdept = 'Computer Science'
Intersect
Select Sno From Student Where Sage <= 19
结果如下:
Select Sno From SC Where Cno = '1'
Intersect
Select Sno From SC Where Cno = '2'
结果如下:
Select Sno, Sage From Student Where Sdept = 'Computer Science'
Except
Select Sno,Sage From Student Where Sage <= 19
结果如下:
子查询不仅可以嵌套在SELECT语句中用以构造父查询的条件,也可以嵌套在 INSERT语句中用以生成要插入的批量数据。
插入子查询结果的INSERT语句格式为
INSERT
INTO<表名>[(<属性列1>[,<属性列2>…])子查询;
首先在数据库中建立一个新表,其中一列存放系名,另一列存放相应的学生平均年龄。
然后对 Student表按系分组求平均年龄,再把系名和平均年龄存入新表中。
Create Table Dept_avg(
Sdept char(40),
Avg_ SmallInt
)
Insert Into Dept_avg(Sdept, Avg_)
Select Sdept, Avg(Sage) From Student Group By(Sdept)
Select * From Dept_avg
结果如下:
修改操作又称为更新操作,其语句的一般格式为:
UPDATE<表名>
SET<列名>=<表达式>[,列名>-<表达式>]…
[WHERE<条件>];
其功能是修改指定表中满足 WHERE子句条件的元组。其中 SET子句给出<表达式>的值用于取代相应的属性列值。如果省略WHERE子句,则表示要修改表中的所有元组。
Update Student
Set Sage = 22
Where Sno = '20191102062'
结果如下:
Update Student
Set Sage = Sage + 1
Update SC
Set Grade = 0
Where Sno In(
Select Sno From Student
Where Sdept = 'Computer Science'
)
结果如下
删除语句的一般格式为
DELETE
FROM<表名>
[WHERE<条件>];
DELETE 语句的功能是从指定表中删除满足WHERE子句条件的所有元组。如果省略WHERE子句则表示删除表中全部元组,但表的定义仍在字典中。也就是说,DELETE 语句删除的是表中的数据,而不是关于表的定义。
Delete
From Student Where Sno = '20191102062'
发生错误,原因是该Sno是SC的外码, 所以要先删除SC相关的值
Delete From SC
可以发现SC表空了
DELETE
FROM SC
WHERE Sno IN
(SELETE Sno FROM Student
WHERE Sdept= 'CS');
INSERT INTO SC(Sno,Cno,Grade)
VALUES('20191102071','1', NULL);
UPDATE Student SET Sdept = NULL
WHERE Sno='20191102062';
SELECT*
FROM Student
WHERE Sname IS NULL OR Ssex IS NULL OR Sage IS NULL OR Sdept IS NULL;
空值与另一个值(包括另一个空值)的算术运算的结果为空值,空值与另一个值(包括另一个空值)的比较运算的结果为UNKNOWN。有了UNKNOWN 后,传统的逻辑运算中二值(TRUE,FALSE)逻辑就扩展成了三值逻辑。
具体如下表:
在查询语句中,只有使WHERE和HAVING
子句中的选择条件为TRUE的元组才被选出作为输出结果。
SELECT Sno FROM SC
WHERE Grade<60 AND Cno='1';
SELECT Sno FROM SC
WHERE Grade<60 AND Cno='1'UNION
SELECT Sno FROM SC
WHERE Grade IS NULL AND Cno='1';
SQL 语言用 CREATE VIEW命令建立视图,其一般格式为
CREATE VIEW<视图名>[(<列名>[,<列名>]…)]
AS<子查询>
[WITH CHECK OPTION];
其中,子查询可以是任意的SELECT 语句,是否可以含有ORDER BY子句和 DISTINCT短语,则取决于具体系统的实现。WITH CHECK OPTION表示对视图进行UPDATE、INSERT和 DELETE 操作时要保证更新、插入或删除的行满足视图定义中的谓词条件(即子查询中的条件表达式)。
CREATE VIEW IS_Student AS
SELECT Sno,Sname,Sage
FROM Student
WHERE Sdept='information security';
关系数据库管理系统执行CREATE VIEW 语句的结果只是把视图的定义存入数据字典,并不执行其中的SELECT语句。只是在对视图查询时,才按视图的定义从基本表中将数据查出。
CREATE VIEW IS_Student AS
SELECT Sno,Sname,Sage FROM Student
WHERE Sdept='information security'
WITH CHECK OPTION;
视图不仅可以建立在单个基本表上,也可以建立在多个基本表上。
CREATE VIEW IS_S1(Sno,Sname,Grade)
AS SELECT Student.Sno,Sname,Grade FROM Student,sc
WHERE Sdept='IS' AND
Student.Sno=SC.Sno AND
sC.Cno='1';
视图不仅可以建立在一个或多个基本表上,也可以建立在一个或多个已定义好的视图上,或建立在基本表与视图上。
CREATE VIEW IS_S2
AS
SELECT Sno,Sname,Grade FROM IS_S1
WHERE Grade>=90;
这里的视图IS_S2就是建立在视图IS_S1之上的。
CREATE VIEW BT_S(Sno,Sname,Sbirth)
AS
SELECT Sno,Sname,2014-Sage
FROM Student;
这里视图BT_S是一个带表达式的视图。视图中的出生年份值是通过计算得到的。还可以用带有聚集函数和GROUP BY子句的查询来定义视图,这种视图称为分组视图。
CREATE VIEW S_G(Sno,Gavg)AS
SELECT Sno,AVG(Grade) FROM SC
GROUP BY Sno;
CREATE VIEW F_Student(F_sno,name,sex,age,dept)AS
SELECT* FROM Student WHERE Ssex='女';
这里视图F_Student是由子查询"SELECT*"建立的。F_Student视图的属性列与Student表的属性列一一对应。如果以后修改了基本表 Student 的结构,则 Student表与 F_Student视图的映像关系就会被破坏,该视图就不能正常工作了。为避免出现这类问题,最好在修改基本表之后删除由该基本表导出的视图,然后重建这个视图。将
该语句的格式为
DROP VIEW<视图名>[CASCADE];
视图删除后视图的定义将从数据字典中删除。如果该视图上还导出了其他视图,则使用CASCADE 级联删除语句把该视图和由它导出的所有视图一起删除。
DROP VIEW BT_S;
/*成功执行*/
DROP VIEW IS_Sl;
/*拒绝执行*/
执行此语句时由于IS_S1视图上还导出了IS_S2视图,所以该语句被拒绝执行。如果确定要删除,则使用级联删除语句:
DROP VIEW IS_S1 CASCADE;
/*删除了视图IS S1和由它导出的所有视图*/
SELECT Sno,Sage FROM IS_Student WHERE Sage<20;
关系数据库管理系统执行对视图的查询时,首先进行有效性检查,检查查询中涉及的
表、视图等是否存在。如果存在,则从数据字典中取出视图的定义,把定义中的子查询和
用户的查询结合起来,转换成等价的对基本表的查询,然后再执行修正了的查询。这一转
换过程称为视图消解(view resolution)。
SELECT IS_Student.Sno,Sname FROM IS_Student,SC
WHERE IS_Student.Sno=SC.Sno AND SC.Cno='1';
结果如下:
SELECT * FROM S_G
WHERE Gavg>=90;
并未对该语句报错,成功查询:
目前多数关系数据库系统对行列子集视图的查询均能进行正确转换。但对非行列子集视图的查询(如例3.94)就不一定能做转换了,因此这类查询应该直接对基本表进行。
由于视图是不实际存储数据的虚表,因此对视图的更新最终要转换为对基本表的更新。像查询视图那样,对视图的更新操作也是通过视图消解,转换为对基本表的更新操作。
UPDATE IS_Student SET Sname='刘辰'
WHERE Sno='20191102062';
INSERT
INTO IS_Student
VALUES('20191102074','赵新',25);
DELETE
FROM IS_Student
WHERE Sno='201215129';
上篇文章给大家介绍了 Java正则表达式匹配,替换,查找,切割的方法 ,接下来,...
DELETEFROMTablesWHEREIDNOTIN(SELECTMin(ID)FROMTablesGROUPBYName) Min的话保...
Elasticsearch 是通过 Lucene 的倒排索引技术实现比关系型数据库更快的过滤。特...
4月11日20:30~22:00通过腾讯会议进行了第二次在线学习讨论我把学习笔记整理一下...
正则忽略大小写 – RegexOptions.IgnoreCase 例如: 复制代码 代码如下: Str = R...
工具:Eclipse,Oracle,smartupload.jar;语言:jsp,Java;数据存储:Oracle。...
复制代码 代码如下: % URL="http://news.163.com/special/00011K6L/rss_newstop....
错误描述: 在开发.net项目中,通过microsoft.ACE.oledb读取excel文件信息时,报...
项目中用到的一些特殊字符和图标 html代码 XML/HTML Code 复制内容到剪贴板 div ...
本文实例讲述了Laravel框架源码解析之反射的使用。分享给大家供大家参考,具体如...