1.数据定义
1.1模式的定义与删除
1.1.1定义模式
(1).格式:CREATE SCHEMA <模式名> AUTHORIZATION <用户名>;
EG:CREATE SCHEMA "S-T" AUTHORIZATION WANG;
模式名缺省时用户名即为模式名。
EG:CREATE SCHEMA AUTHORIZATION WANG;
(2).在CREATE SCHEMA可以接受CREATE TABLE,CREATE VIE和GRANT子句。
EG:
CREATE SCHEMA TEST AUTHORIZATION WANG
CREATE TABLE TAB1 (…);
(3).执行创建语句必须拥有DBA权限,或者DBA授予在CREATE SCHEMA
的权限。
1.1.2删除模式
格式:DROP SCHEMA <模式名> <CASCADE | RESTRICT>;
---CASCADE | RESTRICT两个参数必须二选一。
---CASCADE(级联):删除模式的同时把该模式中所有的数据库对象删除。
---RESTRICT(限制):如果该模式中定义了下属的数据库对象(表、视图等)则删除失败。
1.2表的定义、删除与修改
1.2.1定义基本表
CREATE TABLE <表名>
(<列名> <数据类型> [<列级完整性约束条件>]
[, <列名> <数据类型> [<列级完整性约束条件>]]…
[, <表级完整性约束条件>]);
/*方括号中的内容可缺省*/
如果完整性约束条件涉及该表的多个属性列,则必须定义在表级上,否则表级列级均可。
EG:建立“学生”表Student,学号为主码,姓名取值唯一
CREATE TABLE Student
(Sno CHAR(9) PRIMARY KEY,
/*列级完整性约束*/
Sname CHAR(20) UNIQUE,
/*Sname取值唯一*/
Ssex CHAR(2),
Sage SMALLINT,
Sdept CHAR(20)
);
EG:建立“课程”表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*/
);
EG:建立“学生选课:表SC
CREATE TABLE SC
(Sno CHAR(9),
Cno CHAR(4),
Grade SMALLINT,
PRIMARY KRY (Sno, Cno),
/*主码由两个属性构成,需作为表级完整性定义*/
FOREIGN KEY (Sno) REFERENCES Student(Sno),
/*表级完整性约束条件,Sno是外码,被参照表是Student*/
FOREIGN KEY (Cno) REFERENCES Course(Sno)
/*表级完整性约束条件,Cno是外码,被参照表是Course*/
)
1.2.2数据类型
数据类型 |
含义 |
CHAR(n) |
长度为n的定长字符串 |
VARCHAR(n) |
最大长度为n的变长字符串 |
INT |
整型 |
SMALLINT |
短整型 |
NUMERIC(p, d) |
定点数,表示总共有p位数字, 并且小数点后有d位 |
REAL |
浮点数 |
Double Precision |
双精度浮点数 |
FLOAT(n) |
浮点数,精度至少为n位数字 |
DATE |
日期(年月日),格式为YYYY-MM-DD |
TIME |
时间(时分秒),格式为HH:MM:SS |
1.2.3完整性约束
/*建立教师表TEACHER,要求每个教师的应发工资
不低于3000元。应发工资是工资列Sal与扣除项Deduct之和*/
CREATE TABLE TEACHER
(Eno NUMERIC(4) PRIMARY KEY, /*在列级定义主码*/
Ename CHAR(10),
Job CHAR(8),
Sal NUMERIC(7,2),
Deduct NUMERIC(7,2),
Deptno NUMERIC(2),
CONSTRAINT TEACHERFKey FOREIGN KEY (Deptno)
REFERENCES DEPT(Deptno),
CONSTRAINT C1 CHECK (Sal + Deduct >= 3000)
);
/*修改表Student中的约束条件,要求学号改为
在900000~999999之间,年龄由小于30改为小于40
(可以先删除原来的约束条件,再增加新的约束条件)*/
ALTER TABLE Student
DROP CONSTRAINT C1;
ALTER TABLE Student
ADD CONSTRAINT C1 CHECK (Sno BETWEEN 900000
AND 999999);
ALTER TABLE Student
DROP CONSTRAINT C3;
ALTER TABLE Student
ADD CONSTRAINT C3 CHECK (Sage < 40);
1.3模式与表
每一个基本表都属于一个模式,一个模式可包含多个基本表。
创建数据库对象时,若没有指定模式,系统会根据搜索路径来确定该对象所属的模式。
1.3.1搜索路径
(1).显示当前搜索路径:
SHOW search_path
(2).搜索路径的默认值:
$user, PUBLIC
(3).设置搜索路径:
SET search_path TO "S-T", PUBLIC
若搜索路径中的模式名都不存在,系统会报错,否则采用第一个模式名作为数据库对象的模式名。
1.3.2创建基本表
(1).创建表时给出模式名
CREATE TABLE "S-T".Student(…);
CREATE TABLE "S-T".Course(…);
CREATE TABLE "S-T".SC(…);
(2).创建模式的同时创建表
CREATE SCHEMA TEST AUTHORIZATION WANG
CREATE TABLE TAB1 (…);
(3).设置搜索路径,不给出模式名
1.4修改基本表
ALTER TABLE <表名>
[ADD [COLUMN] <新列名> <数据类型> [完整性约束]]
[ADD <表级完整性约束>]
[DROP [COLUMN] <列名> [CASCADE | RESTRICT]]
[DROP CONSTRAINT <完整性约束名> [CASCADE | RESTRICT]]
[ALTER COLUMN <列名> <数据类型>];
(1).DROP [COLUMN]
用于删除表中的列。
CASCADE :一并删除引用该列的其他对象。
RESTRICT:如果该列被其他对象引用则删除失败。
(2).DROP CONSTRAINT
用于删除指定的完整性约束条件。
(3).ALTER COLUMN
用于修改原有的列定义,包括列名和数据类型。
/*向Student表中添加“入学时间”列,数据类型为DATE*/
ALTER TABLE Student ADD S_entrence DATE;
/*将年龄的数据类型改为整型*/
ALTER TABLE Student ALTER COLUMN Sage INT;
/*添加课程名必须取值唯一的完整性约束条件*/
ALTER TABLE Course ADD UNIQUE(Cname);
注:不论基本表中原来是否已有数据,新加的列一律为空值(NULL)。由于主码不能为空值,所以在建表时就应确定主码。
1.5删除基本表
DROP TABLE <表名> [CASCADE | RESTRICT];
/*删除Student表*/
DROP TABLE Student CASCADE;
基本表定义被删除,表上建立的索引、视图、触发器一并被删除。
1.6索引的建立和删除
1.索引即目录,可以加快查询速度,DBMS会自动在以下列建立索引:
PRIMARY KRY;
UNIQUE;
2.索引分类:
1).唯一索引;2).非唯一索引;3).聚簇索引。
3.聚簇索引:
--在最经常查询的列建立聚簇索引以提高查询效率。
--一个基本表只能有一个聚簇索引。
--经常更新的列不宜建聚簇索引。
1.6.1建立索引
CREATE [UNIQUE] [CLUSTER] INDEX <索引名> ON <表名>
(<列名> [<次序>] [, <列名> [<次序>]]…);
/*次序为升序:ASC 次序为降序:DESC */
1.6.2删除索引
DROP INDEX <索引名>;
/*从数据字典中删去有关该索引的描述*/
1.7断言
1).SQL中,可以使用 CREATE ASSERTION语句,通过声明性断言来指定更具一般性的约束。
2).可以定义涉及多个表的或聚集操作的比较复杂的完整性约束。
3).断言创建以后,任何对断言中所涉及的关系的操作都会触发关系数据库管理系统对断言的检查,任何使断言不为真值的操作都会被拒绝执行。
1.7.1创建断言
CREATE ASSERTION<断言名><CHECK 子句>;
/*每个断言都被赋予一个名字,<CHECK 子句>中的约束
条件与WHERE子句的条件表达式类似*/
/*限制数据库课程最多60名学生选修*/
CREATE ASSERTION ASSE_SC_DB_NUM
CHECK (60 >= (select count(*)
/*此断言的谓词涉及聚集操作count的SQL语句*/
From Course,SC
Where SC.Cno=Course.Cno and
Course.Cname ='数据库');
/*限制每一门课程最多60名学生选修*/
CREATE ASSERTION ASSE_SC__CNUM1
CHECK (60 >= ALL (SELECT count(*)
FROM SC
Group by cno)
);
/*限制每个学期每一门课程最多60名学生选修
首先需要修改SC表的模式,增加一个“学期(TERM)”属性*/
ALTER TABLE SC ADD TERM DATE;
/*然后,定义断言:*/
CREATE ASSERTION ASSE_SC__CNUM2
CHECK (60 >= ALL (SELECT count(*)
FROM SC
Group by cno,TERM)
);
1.7.2删除断言
DROP ASSERTION <断言名>;
如果断言很复杂,则系统在检测和维护断言时的开销是非常大的,因此在使用断言时需要注意。
1.8触发器
1).用户定义在关系表上的一类由事件驱动的特殊过程,保存在数据库服务器中。
2).任何用户对表的增、删、改操作均由服务器自动激活相应的触发器。
3).触发器可以实施更为复杂的检查和操作,具有更精细和更强大的数据控制能力。
触发器又叫做事件-条件-动作(event-condition-action)规则。
——发生了某个事件就检查某个条件,满足条件就要执行某个动作。
1.8.1创建触发器
CREATE TRIGGER <触发器名>
{BEFORE | AFTER} <触发事件> ON <表名>
REFERENCING NEW|OLD ROW AS<变量>
FOR EACH {ROW | STATEMENT}
[WHEN <触发条件>]<触发动作体>;
1. 表的拥有者或DBA才可以在表上创建触发器。
2. 触发器名:
1).触发器名可以包含模式名,也可以不包含模式名;
2).同一模式下,触发器名必须是唯一的;
3).触发器和表名必须在同一模式下。
3. 表名:触发器的目标表
1).触发器只能定义在基本表上,不能定义在视图上;
2).当基本表的数据发生变化时,将激活定义在该表上相应触发事件的触发器;
4.触发事件:
1).可以是INSERT、DELETE或UPDATE ,也可以是这几个事件的组合,还可以UPDATE OF<触发列,...>,即进一步指明修改哪些列时激活触发器;
2).AFTER/BEFORE是触发的时机:
AFTER表示在触发事件的操作执行之后激活触发器
BEFORE表示在触发事件的操作执行之前激活触发器
5.触发器类型
1).行级触发器(FOR EACH ROW)
2).语句级触发器(FOR EACH STATEMENT)
6.触发条件
1).触发器被激活时,只有当触发条件为真时触发动作体才执行;否则触发动作体不执行。
2).如果省略WHEN触发条件,则触发动作体在触发器激活后立即执行。
7. 触发动作体
1).触发动作体可以是一个匿名PL/SQL过程块也可以是对已创建存储过程的调用。
2).如果是行级触发器,用户都可以在过程体中使用NEW和OLD引用事件之后的新值和事件之前的旧值。
3).如果是语句级触发器,则不能在触发动作体中使用NEW或OLD进行引用。
4).如果触发动作体执行失败,激活触发器的事件就会终止执行,触发器的目标表或触发器可能影响的其他对象不发生任何变化。
/*当对表SC的Grade属性进行修改时,若分数增加了10%则将此次
操作记录到下面表中:
SC_U(Sno,Cno,Oldgrade,Newgrade)
其中Oldgrade是修改前的分数,Newgrade是修改后的分数*/
CREATE TRIGGER SC_T
AFTER UPDATE OF Grade ON SC
REFERENCING
OLD row AS OldTuple,
NEW row AS NewTuple
FOR EACH ROW
WHEN (NewTuple.Grade >= 1.1*OldTuple.Grade)
INSERT INTO SC_U(Sno,Cno,OldGrade,NewGrade)
VALUES(OldTuple.Sno,OldTuple.Cno,OldTuple.Grade,NewTuple.Grade);
/*将每次对表Student的插入操作所增加的学生个数记
录到表StudentInsertLog中。*/
CREATE TRIGGER Student_Count
AFTER INSERT ON Student
/*指明触发器激活的时间是在执行INSERT后*/
REFERENCING
NEW TABLE AS DELTA
FOR EACH STATEMENT
/*语句级触发器, 即执行完INSERT语句后下面的触发动作体才执行一次*/
INSERT INTO StudentInsertLog (Numbers)
SELECT COUNT(*) FROM DELTA;
/*定义一个BEFORE行级触发器,为教师表Teacher定义完整
性规则“教授的工资不得低于4000元,如果低于4000元,自动改为
4000元”。*/
CREATE TRIGGER Insert_Or_Update_Sal
BEFORE INSERT OR UPDATE ON Teacher
REFERENCEING NEW row as newTuple
/*触发事件是插入或更新操作*/
FOR EACH ROW /*行级触发器*/
BEGIN /*定义触发动作体,是PL/SQL过程块*/
IF (new.Job='教授') AND (new.Sal < 4000) THEN
new.Sal =4000;
END IF;
END;
1.8.3删除触发器
DROP TRIGGER <触发器名> ON <表名>;
触发器必须是一个已经创建的触发器,并且只能由具有相应权限的用户删除。
2.数据查询
查询三步:
查哪些信息?从哪个表查?按什么条件查?
SELECT [ALL | DISTINCT] <目标列表达式>
[, <目标列表达式>]…
FROM <表名或视图名> [, <表名或视图名>]…
[WHERE <条件表达式>]
[GROUP BY <列名> [HAVING <条件表达式>]]
[ORDER BY <列名> [ASC | DESC]];
2.1单表查询
2.1.1查询若干列
SELECT Sno, Sname FROM Student;
SELECT * FROM Student;
目标列表达式:
1).算术表达式。2).字符串常量。3).函数。4).列别名。
SELECT Sname NAME, 'Year Of Birth:' BIRTH, 2004-Sage BIRTHDAY,
LOWER(Sdept) DEPARTMENT FROM Student;
查询结果:
NAME |
BIRTH |
BIRTHDAY |
DEPARTMENT |
李勇 |
Year Of Birth: |
1994 |
cs |
刘畅 |
Year Of Birth: |
1995 |
ma |
王明 |
Year Of Birth: |
1993 |
is |
2.1.2查询表中若干元组
1.取消重复行
指定DISTINCT关键词,没有指定则缺省为ALL。
2.查询满足条件的元组
WHERE子句实现:
/*比较大小*/
/*查询计算机系的所有学生*/
SELECT Sname FROM Student WHERE Sdept = 'CS';
/*确定范围*/
/*查询年龄不在20-23的学生的姓名、系别、年龄*/
SELECT Sname, Sdept, Sage
FROM Student WHERE Sage NOT BETWEEN 20 AND 23;
/*确定集合*/
/*查询不是信息系、数学系、计算机系的学生*/
SELECT Sname, Sex FROM
WHERE Sdept NOT IN ('IS', 'MA', 'CS');
/*字符匹配*/
/*查询所有不姓刘的学生的相关信息*/
SELECT Sname, Sno, Ssex FROM Student
WHERE Sname NOT LIKE '刘%';
/*查询所有名字中第二个字为阳的学生的相关信息*/
SELECT Sname, Sno, Ssex FROM Student
WHERE Sname LIKE '_阳%';
/*查询以"DB_"开头,倒数第三个字符为i的课程的详细信息*/
SELECT * FROM Course
WHERE Cname LIKE 'DB\_%i__' ESCAPE '\';
/*涉及空值的查询*/
/*查询所有有成绩的学生的学号和课程号
IS不能用=代替*/
SELECT Sno, Cno FROM SC
WHERE Grade IS NOT NULL;
2.1.3ORDER BY子句
1).升序:ASC
2).降序:DESC
3).缺省值为ASC,空值默认最大(mysql中实测NULL是默认最小的)。
/*查询全体学生情况,查询结果按系号升序排列,
同一系按年龄降序排列*/
SELECT * FROM Student
ORDER BY Sdept, Sage DESC;
2.1.4聚集函数
/*查询选修了课程的学生人数*/
SELECT COUNT(DISTINCT Sno) FROM SC;
/*查询特定学号的学生选修的总学分数*/
SELECT SUM(Ccredit) FROM SC, Course WHERE
Sno = '2002188' AND SC.Cno = Course.Cno;
2.1.5GROUP BY子句
分组后聚集函数作用于每个组。
/*课程号即对应的选课人数*/
SELECT Cno, COUNT(Sno) FROM SC GROUP BY Cno;
分组后可以用HAVING指定筛选条件。
/*选修了3门以上课程的学生的学号*/
SELECT Sno FROM SC GROUP BY Sno HAVING COUNT(*) > 3;
2.2连接查询
2.2.1等值与非等值连接
在WHERE子句中添加条件将若干表连接起来,称该条件为连接条件。
/*格式一*/
[<表名1>.]<列名1> <比较运算符> [<表名2>.]<列名2>;
/*格式二*/
[<表名1>.]<列名1> BETWEEN [<表名2>.]<列名2> AND [<表名3>.]<列名3>;
/*EG*/
/*查询每个学生及其选修课程的情况*/
SELECT Student.*, SC.*
FROM Student, SC
WHERE Student.Sno=SC.Sno;
2.2.2自身连接
即一个表与自身连接。
1).需要给表起别名加以区分。
2).由于所有属性同名,需要给属性加别名前缀。
/*查询每一门课程的间接先修课*/
SELECT FIRST.Cno, SECOND.Cpno
FROM Course FIRST, Course SECOND
WHERE FIRST.Cpno = SECOND.Cno;
给第一个Course表取名FIRST,第二个表取名SECOND。
查询结果:
2.2.3外连接
/*左外连接*/
LEFT OUT JOIN SC ON
/*右外连接*/
RIGHT OUT JOIN SC ON
/*查询每个学生及其选修课程的情况(包括还未选课)*/
SELECT Student.Sno, Sname, Ssex, Sage, Sdept, Cno, Grade
FROM Student LEFT OUT JOIN SC ON (Student.Sno=SC.Sno);
2.2.4多表连接
两个以上表进行连接。
/*查询每个学生的相关信息*/
SELECT Student.Sno, Sname, Cname, Grade
FROM Student, SC, Course
WHERE Student.Sno = SC.Sno AND SC.Sno = Course.Sno;
2.3嵌套查询
一个SELECT-FROM-WHERE语句称一个查询块,嵌套查询指将一个查询块嵌套在另一个查询块的WHERE子句或HAVING短语中的条件中的查询。
注:子查询中不能用ORDER BY子句。
1).不相关子查询:子查询的查询条件不依赖于父查询。
由里向外逐层处理。即每个子查询在上一级查询处理之前求解,子查询的结果用于建立其父查询的查找条件。
2).相关子查询:子查询的查询条件依赖于父查询。
首先取外层查询中表的第一个元组,根据它与内层查询相关的属性值处理内层查询,若WHERE子句返回值为真,则取此元组放入结果表然后再取外层表的下一个元组,重复这一过程,直至外层表全部检查完为止
2.3.1带IN的子查询
/*查询与刘晨在一个系的学生的相关信息*/
SELECT Sno, Sname, Sdept
FROM Student
WHERE Sdept IN
(SELECT Sdept
FROM Student
WHERE Sname = '刘晨');
2.3.2带比较运算符的子查询
/*找出每个学生超过他选修课程平均成绩的课程号
(相关子查询)*/
SELECT Sno, Cno
FROM SC x
WHERE Grade >=
(SELECT AVG(Grade)
FROM SC y
WHERE y.Sno=x.Sno);
2.3.3带ANY/ALL的子查询
ANY(SOME)——任意一个值
ALL——所有值
/*查询非计算机系中比计算机科学系任意
一个学生年龄小的学生姓名和年龄*/
SELECT Sname, Sage
FROM Student
WHERE Sage <
ANY (SELECT Sage
FROM Student
WHERE Sdept= ' CS ')
AND Sdept <> 'CS' ;
/*上述例子的聚集函数实现*/
SELECT Sname,Sage
FROM Student
WHERE Sage <
(SELECT MIN(Sage)
FROM Student
WHERE Sdept= ' CS ')
AND Sdept <>' CS ';
聚集函数、ANY/ALL、IN的转换关系(使用聚集函数效率更高):
2.3.4带EXISTS的子查询
1).带有EXISTS谓词的子查询不返回任何数据,只产生逻辑真值“true”或逻辑假值“false”。
若内层查询结果非空,则外层的WHERE子句返回真值。
若内层查询结果为空,则外层的WHERE子句返回假值。
2).由EXISTS引出的子查询,其目标列表达式通常都用 * ,因为带EXISTS的子查询只返回真值或假值,给出列名无实际意义。
3).对于父查询中的每个元组,都检查EXISTS的返回值,返回真则处理后加入查询结果。
4).与连接的区别:
连接是先将若干表连接成一张大表再进行条件检查,EXISTS是对前一个表中的元组一次检查,EXISTS效率较高。
/*查询所有选修了1号课程的学生的姓名*/
SELECT Sname
FROM Student
WHERE EXISTS
(SELECT *
FROM SC
WHERE Sno=Student.Sno AND Cno = '1');
/*查询与刘晨在一个系的学生*/
SELECT Sno,Sname,Sdept
FROM Student S1
WHERE EXISTS
(SELECT *
FROM Student S2
WHERE S2.Sdept = S1.Sdept AND
S2.Sname = '刘晨');
5).用EXISTS/NOT EXISTS实现全称量词
(∀x) P = ¬(∃x (¬P) )
EG:
查询选修了全部课程的学生
= 没有一门课不选修的学生。
SELECT Sname
FROM Student
WHERE NOT EXISTS
(SELECT *
FROM Course
WHERE NOT EXISTS
(SELECT *
FROM SC
WHERE Sno= Student.Sno
AND Cno= Course.Cno));
5).用EXISTS/NOT EXISTS实现逻辑蕴含
p -> q = ¬p V q
EG:查询至少选修了学生201215122选修的全部课程的学生号码。
= 不存在这样的课程y,学生201215122选修了,但是学生x并没有选。
(x为需要查询的学生)
SELECT DISTINCT SCX.Sno
FROM SC SCX
WHERE NOT EXISTS
(SELECT *
FROM SC SCY
WHERE SCY.Sno = ' 201215122 ' AND
NOT EXISTS
(SELECT *
FROM SC SCZ
WHERE SCZ.Sno=SCX.Sno AND
SCZ.Cno=SCY.Cno));
2.4集合查询
集合操作的种类:并、交、差。
集合操作是行操作,参加集合操作的各查询结果列数必须相同。
2.4.1并操作UNION
EG:查询计科系以及年龄不大于19岁的学生的信息。
SELECT * FROM Student WHERE Sdept = 'CS'
UNION
SELECT * FROM Student WHERE Sage <= 19;
UNION:将多个查询结果合并起来时,系统自动去掉重复元组。
UNION ALL:将多个查询结果合并起来时,保留重复元组。
2.4.2交操作INTERSECT
EG:查询计科系中年龄不大于19岁的学生的信息。
SELECT * FROM Student WHERE Sdept = 'CS'
INTERSECT
SELECT * FROM Student WHERE Sage <= 19;
2.4.3差操作EXCEPT
EG:查询计科系中年龄大于19岁的学生的信息。
SELECT * FROM Student WHERE Sdept = 'CS'
EXCEPT
SELECT * FROM Student WHERE Sage <= 19;
2.5基于派生表的查询
子查询不仅可以出现在WHERE子句中,还可以出现在FROM子句中,这时子查询生成的临时派生表(Derived Table)成为主查询的查询对象。
EG:找出每个学生超过他自己选修课程平均成绩的课程号。
SELECT Sno, Cno
FROM SC, (SELECT Sno, 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子句后面的列名为其缺省属性。
EG:查询所有选修了1号课程的学生姓名。
SELECT Sname
FROM Student,
(SELECT Sno FROM SC WHERE Cno=' 1 ') AS SC1
WHERE Student.Sno=SC1.Sno;
3.数据更新
3.1插入数据
3.1.1插入元组
将新元组插入指定表中:
INSERT INTO <表名> [(<属性列1>[, <属性列2>]…)]
VALUES (<常量1>[,<常量2>…]);
INTO子句中的属性列顺序不做要求,VALUES子句的值必须与INTO子句匹配,未指定VALUE的属性自动赋NULL,但主码不能为空。
EG:向Student表插入一个元组。
INSERT
INTO Student (Sno,Sname,Ssex,Sdept,Sage)
VALUES ('201215128','陈冬','男','IS',18);
/*缺省属性列参数*/
INSERT
INTO Student
VALUES ('201215128','陈冬','男','IS',18);
3.1.2插入子查询结果
INSERT INTO <表名> [(<属性列1>[, <属性列2>]…)]
子查询;
EG:对每一个系,求学生的平均年龄,并把结果存入数据库。
/*第一步:建表*/
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;
3.2修改数据
UPDATE <表名>
SET <列名> = <表达式>[, <列名> = <表达式>]…[WHERE <条件>];
1).修改指定表中满足WHERE子句条件的元组。
2).SET子句给出<表达式>的值用于取代相应的属性列。
3).如果省略WHERE子句,表示要修改表中的所有元组。
3.2.1修改某一个元组的值
/*将学生201215121的年龄改为22岁*/
UPDATE Student
SET Sage=22
WHERE Sno='201215121';
3.2.2修改多个元组的值
/*将所有学生的年龄增加1岁*/
UPDATE Student
SET Sage= Sage+1;
3.2.3带子查询的修改语句
/*将计算机科学系全体学生的成绩置零*/
UPDATE SC
SET Grade=0
WHERE Sno IN
(SELETE Sno
FROM Student
WHERE Sdept= 'CS');
3.3删除数据
DELETE FROM <表名> [WHERE <条件>];
WHERE子句可指定要删除的元组,无该子句将会删除表中的全部元组,但是表的定义还在。
3.3.1删除某一个元组的值
/*删除学号为200215128的学生记录*/
DELETE
FROM Student
WHERE Sno='200215128';
3.3.2修改多个元组的值
/*将所有学生的选课记录删除*/
DELETE FROM SC;
3.3.3带子查询的删除语句
/*删除计算机科学系所有学生的选课记录*/
DELETE FROM SC
WHERE Sno IN
(SELECT Sno
FROM Student
WHERE Sdept= 'CS');
4.空值的处理
4.1空值的产生
/*该学生还没有考试成绩,取空值*/
INSERT INTO SC(Sno,Cno,Grade)
VALUES('201215126 ','1',NULL);
/*VALUE缺省,自动赋空值*/
INSERT INTO SC(Sno,Cno)
VALUES(' 201215126 ','1');
4.2空值的判断
IS NULL/IS NOT NULL
/*从Student表中找出漏填了性别或年龄的学生信息*/
SELECT *
FROM Student
WHERE Ssex IS NULL OR Sage IS NULL;
4.3空值的约束条件
1)有NOT NULL约束条件的不能取空值。
2).加了UNIQUE限制的属性列取值唯一。
3).码属性不能取空值。
4.4控制的运算
1).空值与另一个值(包括另一个空值)的算术运算的结果为空值。
2).空值与另一个值(包括另一个空值)的比较运算的结果为UNKNOWN。
3).有UNKNOWN后,传统二值(TRUE,FALSE)逻辑就扩展成了三值逻辑。
T——TRUE
F——FALSE
U——UNKNOW
/*找出选修1号课程的不及格的学生*/
SELECT Sno
FROM SC
WHERE Grade < 60 AND Cno='1';
/*查询结果不包括缺考的学生,因为他们的Grade值为null*/
5.视图
视图的特点:
1).虚表,是从一个或几个基本表(或视图)导出的表
2).只存放视图的定义,不存放视图对应的数据
3).基本表中的数据发生变化,从视图中查询出的数据也随之改变
基于视图的操作:
查询、删除、受限更新、定义基于当前视图的新视图。
5.1定义视图
5.1.1建立视图
CREATE VIEW
<视图名> [(<列名> [,<列名>]…)]
AS <子查询>
[WITH CHECK OPTION];
1).属性列名要么全部省略,要么全部指定。
2).子查询不能含有ORDER BY子句和DISTINCT短语。
3).CREATE VIEW只是建立视图的定义,并不执行SELECT语句。
4).WITH CHECK OPTION:对视图进行UPDATE,INSERT和DELETE操作时要保证更新、插入或删除的行满足视图定义中的谓词条件(即子查询中的条件表达式)。
/*多表视图*/
/*建立信息系选修了1号课程的学生的视图(包括学号、姓名、成绩)*/
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';
/*基于视图的视图*/
/*建立信息系选修了1号课程且成绩在90分以上的学生的视图*/
CREATE VIEW IS_S2
AS
SELECT Sno,Sname,Grade
FROM IS_S1
WHERE Grade>=90;
/*带表达式的视图*/
/*定义一个反映学生出生年份的视图*/
CREATE VIEW BT_S(Sno,Sname,Sbirth)
AS
SELECT Sno,Sname,2022-Sage
FROM Student;
/*分组视图*/
/*将学生的学号及平均成绩定义为一个视图*/
CREATE VIEW S_G(Sno,Gavg)
AS
SELECT Sno,AVG(Grade)
FROM SC
GROUP BY Sno;
5.1.2删除视图
DROP VIEW <视图名> [CASCADE];
1).该语句从数据字典中删除指定的视图定义。
2).如果该视图上还导出了其他视图,必须使用CASCADE级联删除语句,把该视图和由它导出的所有视图一起删除。
3).删除基本表时,由该基本表导出的所有视图定义都必须显式地使用DROP VIEW语句删除。
5.2查询视图
5.2.1视图消解法
——关系数据库管理系统实现视图查询的方法
1).进行有效性检查。
2).转换成等价的对基本表的查询。
3).执行修正后的查询。
/*对视图的查询*/
SELECT Sno,Sage
FROM IS_Student
WHERE Sage<20;
/*转化为对基本表的查询*/
SELECT Sno,Sage
FROM Student
WHERE Sdept= 'IS' AND Sage<20;
5.2.2视图消解法的局限性
有些情况不能生成正确的查询。
/*在S_G视图中查询平均成绩在90分以上的学生学号和平均成绩*/
/*对视图的查询*/
SELECT *
FROM S_G
WHERE Gavg>=90;
/*转化后的查询(错误)*/
SELECT Sno,AVG(Grade)
FROM SC
WHERE AVG(Grade)>=90
GROUP BY Sno;
/*正确查询*/
SELECT Sno,AVG(Grade)
FROM SC
GROUP BY Sno
HAVING AVG(Grade)>=90;
5.3更新视图
更新视图指通过视图来插入、修改、删除数据,对视图的更新操作将通过视图消解转化为对基本表的操作。
1).向信息系学生视图IS_Student中插入一个新的学生记录,其中学号为”201215129”,姓名为”赵新”,年龄为20岁:
INSERT
INTO IS_Student
VALUES(‘201215129’,’赵新’,20);
/*转换后*/
INSERT
INTO Student(Sno,Sname,Sage,Sdept)
VALUES(‘200215129 ','赵新',20,'IS' );
2).将信息系学生视图IS_Student中学号 ”201215122”的学生姓名改为”刘辰”:
UPDATE IS_Student
SET Sname= '刘辰'
WHERE Sno= '201215122';
/*转换后的语句*/
UPDATE Student
SET Sname= '刘辰'
WHERE Sno= '201215122' AND Sdept= 'IS';
3).删除信息系学生视图IS_Student中学号为"201215129"的记录:
DELETE
FROM IS_Student
WHERE Sno= '201215129';
/*转换后*/
DELETE
FROM Student
WHERE Sno= '201215129' AND Sdept= 'IS';
4).更新视图的限制:一些视图是不可更新的,因为对这些视图的更新不能唯一地有意义地转换成对相应基本表的更新。
UPDATE S_G
SET Gavg=90
WHERE Sno= '201215121'
Gavg是根据基本表算出来的平均成绩,修改Gavg不能转化为唯一的对基本表的修改。
5.4视图的作用
1).视图能够简化用户的操作。
2).视图使用户能以多种角度看待同一数据。
3).视图对重构数据库提供了一定程度的逻辑独立性。
4).视图能够对机密数据提供安全保护。
5).适当的利用视图可以更清晰的表达查询。