①集数据定义(DDL)、数据操纵(DML)、数据控制(DCL)于一体
②独立完成全部活动 ③运行同时可随时修改 ④数据操作符统一
SQL只要提“做什么”,无需了解存取路径
①SQL是独立的语言
②SQL又是嵌入式语言(C、C++、Java)
SQL中一个关系对应一个基本表
一个(或多个)基本表对应一个存储文件
学生-课程模式 S-T :
学生表:Student(Sno,Sname,Ssex,Sage,Sdept)
课程表:Course(Cno,Cname,Cpno,Ccredit)
学生选课表:SC(Sno,Cno,Grade)
为用户WANG定义一个学生-课程模式S-T
CREATE SCHEMA “S-T” AUTHORIZATION WANG;
//AUTHORIZATION 指的是管理员
在这个空间中可以定义该模式包含的数据库对象,例如基本表、视图、索引等
在CREATE SCHEMA中可以接受CREATETABLE,CREATE VIEW和GRANT子句。
为用户ZHANG创建了一个模式TEST,并且在其中定义一个表TAB1
CREATE SCHEMA TEST AUTHORIZATION ZHANG
CREATE TABLE TAB1 ( COL1 SMALLINT,
COL2 INT,);
DROP SCHEMA <模式名>
CASCADE(级联):删除模式的同时把该模式中所有的数据库对象全部删除
RESTRICT(限制):如果该模式中定义了下属的数据库对象(如表、视图等),则拒绝该删除语句的执行。
DROP SCHEMA ZHANG CASCADE;
删除模式ZHANG,同时该模式中定义的表TAB1也被删除
定义基本表
CREATE TABLE <表名>
(<列名> <数据类型>[ <列级完整性约束条件> ]
[,<列名> <数据类型>[ <列级完整性约束条件>] ]
如果完整性约束条件涉及到该表的多个属性列,则必须定义在表级上,否则既可以定义在列级也可以定义在表级。
建立Student表
CREATE TABLE Student
(Sno CHAR(9) PRIMARY KEY, //列级完整性约束条件,Sno是主码*/
Sname CHAR(20) UNIQUE, // Sname取唯一值
Ssex CHAR(2),
Sage SMALLINT,
Sdept CHAR(20)
);
建立Course表
CREATE TABLE Course
(Cno CHAR(4) PRIMARY KEY,
Cname CHAR(40),
Cpno CHAR(4),
Ccredit SMALLINT,
FOREIGN KEY (Cpno) REFERENCES Course(Cno)
// Cpno是外码,被参照表是Course,被参照列是Cno
);
建立SC表
CREATE TABLE SC
(Sno CHAR(9),
Cno CHAR(4),
Grade SMALLINT,
PRIMARY KEY (Sno,Cno),
/* 主码由两个属性构成,必须作为表级完整性进行定义*/
FOREIGN KEY (Sno) REFERENCES Student(Sno),
/* 表级完整性约束条件,Sno是外码,被参照表是Student */
FOREIGN KEY (Cno)REFERENCES Course(Cno)
/* 表级完整性约束条件, Cno是外码,被参照表是Course*/
);
①每一个基本表都属于一个模式
②一个模式包含多个表
ALTER TABLE <表名>
[ ADD[COLUMN] <新列名> <数据类型> [ 完整性约束 ] ]
[ ADD <表级完整性约束>]
[ DROP [ COLUMN ] <列名> [CASCADE| RESTRICT] ]
[ DROP CONSTRAINT<完整性约束名>[ RESTRICT | CASCADE ] ]
[ALTER COLUMN <列名><数据类型> ] ;
1.向Student表增加“入学时间”列,其数据类型为日期型
ALTER TABLE Student ADD S_entrance DATE;
2.将年龄的数据类型由字符型(假设原来的数据类型是字符型)改为整数
ALTER TABLE Student ALTER COLUMN Sage INT;
3.增加课程名称必须取唯一值的约束条件。
ALTER TABLE Course ADD UNIQUE(Cname);
DROP TABLE <表名>[RESTRICT| CASCADE];
1.删除Student表
DROP TABLE Student CASCADE;
建立索引目的:加快查询速度
谁创建索引:数据库管理员或表主人
谁维护索引:关系数据库管理系统自动完成
如何使用索引:关系数据库管理系统自动选择合适的索引作为存取路径,用户不必也不能显式地选择索引
[例3.13] 为学生-课程数据库中的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);
ALTER INDEX <旧索引名> RENAME TO <新索引名>
1.将SC表的SCno索引名改为SCSno
ALTER INDEX SCno RENAME TO SCSno;
DROP INDEX <索引名>;
删除索引时,系统会从数据字典中删去有关该索引的
描述。
1. 删除Student表的Stusname索引
DROP INDEX Stusname;
数据字典是关系数据库管理系统内部的系统表,记录了所有定义信息:
关系模式、视图、索引、完整性约束、各类用户对数据库操作权限、统计信息
1.查询全体学生的学号与姓名。
SELECT Sno,Sname
FROM Student;
2.查询全体学生的详细记录
SELECT Sno,Sname,Ssex,Sage,Sdept
FROM Student;
或
SELECT *
FROM Student;
3.查全体学生的姓名及其出生年份。
SELECT Sname,2024-Sage
FROM Student;
4.用列别名修改结果
SELECT Sname NAME,'Year of Birth:' BIRTH,
2024-Sage BIRTHDAY,LOWER(Sdept) DEPARTMENT
FROM Student;
①比较大小
1.查询所有年龄在20岁以下的学生姓名及其年龄。
SELECT Sname,Sage
FROM Student
WHERE Sage < 20;
2.查询考试成绩有不及格的学生的学号。
SELECT DISTINCT Sn
FROM SC
WHERE Grade<60;
②确定范围
谓词: BETWEEN … AND …
NOT BETWEEN … AND …
1.查询年龄在20~23岁(包括20岁和23岁)之间的学生的姓名、系别和年龄
SELECT Sname, Sdept, Sage
FROM Student
WHERE Sage BETWEEN 20 AND 23;
③确定集合
谓词:IN <值表>, NOT IN <值表>
1.查询计算机科学系(CS)、数学系(MA)和信息系(IS)学生的姓名和性别。
SELECT Sname, Ssex
FROM Student
WHERE Sdept IN ('CS','MA’,'IS' );
④字符匹配
谓词: [NOT] LIKE ‘<匹配串>’ [ESCAPE ‘ <换码字符>’]
<匹配串>可以是一个完整的字符串,也可以含有通配符%和 _
1.查询所有姓刘学生的姓名、学号和性别。
SELECT Sname, Sno, Ssex
FROM Student
WHERE Sname LIKE '刘%';
2.查询姓"欧阳"且全名为三个汉字的学生的姓名。
SELECT Sname
FROM Student
WHERE Sname LIKE '欧阳__';
⑤涉及空值查询
谓词: IS NULL 或 IS NOT NULL
“IS” 不能用 “=” 代替
[例3.36] 某些学生选修课程后没有参加考试,所以有选课记录,但没 有考试成绩。查询缺少成绩的学生的学号和相应的课程号。
SELECT Sno,Cno
FROM SC
WHERE Grade IS NULL
⑥多重条件查询
逻辑运算符:AND和 OR来连接多个查询条件
AND的优先级高于OR
可以用括号改变优先级
1.查询计算机系年龄在20岁以下的学生姓名。
SELECT Sname
FROM Student
WHERE Sdept= 'CS' AND Sage<20;
1.查询选修了3号课程的学生的学号及其成绩,查询结果按分数降序排列。
SELECT Sno, Grade
FROM SC
WHERE Cno= ' 3 '
ORDER BY Grade DESC;
ASC为升序;DESC为降序;
聚集函数:
统计元组个数
COUNT(*)
统计一列中值的个数
COUNT([DISTINCT|ALL] <列名>)
计算一列值的总和(此列必须为数值型)
SUM([DISTINCT|ALL] <列名>)
计算一列值的平均值(此列必须为数值型)
AVG([DISTINCT|ALL] <列名>)
求一列中的最大值和最小值
MAX([DISTINCT|ALL] <列名>)
MIN([DISTINCT|ALL] <列名>)
细化聚集函数的作用对象:
①如果未对查询结果分组,聚集函数将作用于整个查询结果
②对查询结果分组后,聚集函数将分别作用于每个组
③按指定的一列或多列值分组,值相等的为一组
查询选修了3门以上课程的学生学号。
SELECT Sno
FROM SC
GROUP BY Sno
HAVING COUNT(*) >3;
连接查询:同时涉及两个以上的表的查询
连接条件或连接谓词:用来连接两个表的条件
1.查询每个学生及其选修课程的情况
SELECT Student.*, SC.*
FROM Student, SC
WHERE Student.Sno = SC.Sno;
2.查询选修2号课程且成绩在90分以上的所有学生的学号和姓名。
SELECT Student.Sno, Sname
FROM Student, SC
WHERE Student.Sno=SC.Sno AND SC.Cno=' 2 ' AND SC.Grade>90;
自身连接:一个表与其自己进行连接
需要给表起别名以示区别
1.查询每一门课的间接先修课(即先修课的先修课)
SELECT FIRST.Cno, SECOND.Cpno
FROM Course FIRST, Course SECOND
WHERE FIRST.Cpno = SECOND.Cno;
外连接与普通连接的区别:
①普通连接操作只输出满足连接条件的元组
②外连接操作以指定表为连接主体,将主体表中不满足连接条件的元组一并输出
左外连接
SELECT Student.Sno,Sname,Ssex,Sage,Sdept,Cno,Grade
FROM Student LEFT OUT JOIN SC ON (Student.Sno=SC.Sno);
多表连接:两个以上的表进行连接
查询每个学生的学号、姓名、选修的课程名及成绩
SELECT Student.Sno, Sname, Cname, Grade
FROM Student, SC, Course /*多表连接*/
WHERE Student.Sno = SC.Sno
AND SC.Cno = Course.Cno;
嵌套查询:
①一个SELECT-FROM-WHERE语句作为一个查询块
②将另一个查询块嵌套在WHERE语句中
③子查询不能使用ORDER BY语句
不相关子查询:子查询查询条件不依赖于父查询
相关子查询:子查询查询条件依赖于父查询
1.查询与“刘晨”在同一个系学习的学生。
此查询要求可以分步来完成
① 确定“刘晨”所在系名
SELECT Sdept
FROM Student
WHERE Sname= ' 刘晨 ';
结果为: CS
② 查找所有在CS系学习的学生。
SELECT Sno, Sname, Sdept
FROM Student
WHERE Sdept= ' CS ';
最终:
SELECT Sno, Sname, Sdept FROM Student
WHERE Sdept IN
(SELECT Sdept
FROM Student
WHERE Sname= ' 刘晨 ');
用自身连接完成查询要求
SELECT S1.Sno, S1.Sname,S1.Sdept
FROM Student S1,Student S2
WHERE S1.Sdept = S2.Sdept AND S2.Sname = '刘晨';
1.找出每个学生超过他选修课程平均成绩的课程号。
SELECT Sno, Cno
FROM SC x
WHERE Grade >=(SELECT AVG(Grade) FROM SC y WHERE y.Sno=x.Sno);
1.查询非计算机科学系中比计算机科学系所有学生年龄都小的学生姓名及年龄。
SELECT Sname,Sage
FROM Student
WHERE Sage < ALL
(SELECT Sage
FROM Student
WHERE Sdept= ' CS ')
带有EXISTS子查询不返回任何数据,只产生逻辑“true”或“false”
由EXISTS引出的子查询,其目标列表达式通常都用",因为带EXISTS的子查询只返回真值或假值,给出列名无实际意义。
1.查询所有选修了1号课程的学生姓名。
SELECT Sname
FROM Student
WHERE EXISTS
(SELECT *
FROM SC
WHERE Sno=Student.Sno AND Cno= ' 1 ');
所有带IN谓词、比较运算符、ANY和ALL谓词子查询都能用带EXISTS谓词子查询替代
1.查询选修了全部课程的学生姓名。
SELECT Sname
FROM Student
WHERE NOT EXISTS
(SELECT *
FROM Course
WHERE NOT EXISTS
(SELECT *
FROM SC
WHERE Sno= Student.Sno
AND Cno= Course.Cno
)
);
种类:
并操作UNION
交操作:INTERSECT
差操作:EXCEPT
参加集合操作的各查询结果的列数必须相同;对应项的数据类型也必须相同
1.查询计算机科学系的学生及年龄不大于19岁的学生。
SELECT *
FROM Student
WHERE Sdept= 'CS'
UNION
SELECT *
FROM Student
WHERE Sage<=19;
UNION:将多个查询结果合并起来时,系统自动去掉重复元组
UNION ALL:将多个查询结果合并起来时,保留重复元组
2.查询既选修了课程1又选修了课程2的学生。
SELECT Sno
FROM SC
WHERE Cno=' 1 '
INTERSECT
SELECT Sno
FROM SC
WHERE Cno='2 ';
3.查询计算机科学系的学生与年龄不大于19岁的学生的差集。
SELECT *
FROM Student
WHERE Sdept='CS'
EXCEPT
SELECT *
FROM Student
WHERE Sage <=19;
子查询可以放于FROM子句中,成为主查询的查询对象
1.找出每个学生超过他自己选修课程平均成绩的课程号
SELECT Sno, Cno
FROM SC, (SELECTSno, Avg(Grade)
FROM SC
GROUP BY Sno)
AS Avg_sc(avg_sno,avg_grade)
WHERE SC.Sno = Avg_sc.avg_sno
and SC.Grade >=Avg_sc.avg_grade
SELECT [ALL|DISTINCT]
<目标列表达式> [别名] [ ,<目标列表达式> [别名]] …
FROM <表名或视图名> [别名]
[ ,<表名或视图名> [别名]] …
|(
INSERT
INTO <表名> [(<属性列1>[,<属性列2 >…)]
VALUES (<常量1> [,<常量2>]… );
将一个新学生元组(学号:201215128;姓名:陈冬;性别:男;所在系:IS;年龄:18岁)插入到Student表中。
INSERT
INTO Student (Sno,Sname,Ssex,Sdept,Sage)
VALUES ('201215128','陈冬','男','IS',18);
INSERT
INTO <表名> [(<属性列1> [,<属性列2>… )]
子查询;
对每一个系,求学生的平均年龄,并把结果存入数据库
第一步:建表
CREATE TABLE Dept_age
( Sdept CHAR(15) /*系名*/
Avg_age SMALLINT); /*学生平均年龄*/
第二步:插入数据
INSERT
INTO Dept_age(Sdept,Avg_age)
SELECT Sdept,AVG(Sage)
FROM Student
GROUP BY Sdept;
UPDATE Student
SET Sage=22
WHERE Sno=' 201215121 ';
UPDATE Student
SET Sage= Sage+1;
将计算机科学系全体学生的成绩置零。
UPDATE SC
SET Grade=0
WHERE Sno IN
(SELETE Sno
FROM Student
WHERE Sdept= 'CS' );
修改过程中,会检查是否破坏定义的完整性规则:
①实体完整性
②主码不允许修改
③用户定义完整性:NOT NULL约束、UNIQUE约束、值域约束
DELETE
FROM <表名>
[WHERE <条件>];
删除学号为201215128的学生记录。
DELETE
FROM Student
WHERE Sno= 201215128 ';
删除所有的学生选课记录。
DELETE
FROM SC;
删除计算机科学系所有学生的选课记录。
DELETE
WHERE Sno IN
(SELETE Sno
FROM Student
WHERE Sdept= 'CS') ;
空值情况:
①不知道属性具体值
②属性不应该有值
③由于某种原因不便于填写
向SC表中插入一个元组,学生号是”201215126”,课程号是”1”,成绩为空。
INSERT INTO SC(Sno,Cno,Grade)
VALUES('201215126 ','1',NULL); /*该学生还没有考试成绩,取空值*/
或
INSERT INTO SC(Sno,Cno)
VALUES(' 201215126 ','1'); /*没有赋值的属性,其值为空值*/
判断一个属性是否为空值,用IS NULL或IS NOT NULL表示
①NOT NULL约束条件不能取空值
②加了UNIQUE限制属性不能取空值
③码属性不能取空值
空值与另一个值(包括空值)比较结果为UNKNOWN
选出选修1号课程的不及格的学生以及缺考的学生。
SELECT Sno
FROM SC
WHERE Grade < 60 AND Cno='1'
UNION
SELECT Sno
FROM SC
WHERE Grade IS NULL AND Cno='1'
或者
SELECT Sno
FROM SC
WHERE Cno='1' AND (Grade<60 OR Grade IS NULL);
①虚表,从一个或几个基本表导出来的表
②只存放视图定义,不存放数据
③基本表数据变化,视图查询的数据也随之改变
语句格式
CREATE VIEW <视图名> [(<列名> [,<列名>]…)]
AS <子查询>
[WITH CHECK OPTION];
关系数据库管理系统执行CREATE VIEW语句时只是把视图定义存入数据字典,并不执行其中的SELECT语句。
在对视图查询时,按视图的定义从基本表中将数据查出。
建立信息系学生的视图,并要求进行修改和插入操作时仍需保证该视图只有信息系的学生 。
CREATE VIEW IS_Student
AS
SELECT Sno,Sname,Sage
FROM Student
WHERE Sdept= 'IS'
WITH CHECK OPTION;
定义IS_Student视图时加上了WITH CHECK OPTION子句,对该视图进行插入、修改和删除操作时,RDBMS会自动加上Sdept='IS'的条件。
若一个视图是从单个基本表导出的,并且只是去掉了基本表的某些行和某些列,但保留了主码,我们称这类视图为行列子集视图。
DROP VIEW <视图名>[CASCADE];
删除基表时,由该基表导出的所有视图定义都必须显式地使用DROP VIEW语句删除
删除视图BT_S和IS_S1
DROP VIEW BT_S; /*成功执行*/
DROP VIEW IS_S1; /*拒绝执行*/
要删除IS_S1,需使用级联删除:
DROP VIEW IS_S1 CASCADE;
用户角度:查询视图与查询基本表相同
关系数据库管理系统实现视图查询方法:
①进行有效性检查
②转换成等价的对基本表的查询
③执行修正后的查询
向信息系学生视图IS_S中插入一个新的学生记录,其中学号为”201215129”,姓名为”赵新”,年龄为20岁
INSERT
INTO IS_Student
VALUES(‘201215129’,’赵新’,20);
转换为对基本表的更新:
INSERT
INTO Student(Sno,Sname,Sage,Sdept)
VALUES(‘200215129 ','赵新',20,'IS' );
更新的限制:
①简化用户操作
②使用户以多种角度看待同一数据
③对重构数据库提供了一定程度的逻辑独立性
④能够对机密数据提供安全保护
⑤可以更清晰的表达查询