PL/SQL入门——基础的增删改查

最近由于做毕设,又重新看了一遍王珊和萨师煊老师编写的《数据库原理概论》(第四版),再利用PL/SQL将书中最基础的增删改查实现了一遍

所有操作是对以下三个表进行的

学生表Student


课程表Course


选课表SC


首先用system身份登录

-- 创建表空间

create tablespace abc

datafile 'c:\app\text\abc.dbf'

size 10M;

-- 创建用户

create user xiaoming

identified by a123

default tablespace abc;

--

grant connect,resource to xiaoming;

grant create session to xiaoming;

grant create view to xiaoming;


用户和表空间创建完成后,就可以用xiaoming这个身份登录进入数据库操作了


建表操作

--建立学生表
CREATE TABLE Student
(Sno CHAR(9) PRIMARY KEY,
Sname CHAR(20) UNIQUE,
Ssex CHAR(2),
Ssage SMALLINT,
Sdept CHAR(20)
);


--建立课程表
CREATE TABLE Course
(Cno CHAR(4) PRIMARY KEY,
Cname CHAR(40),
Cpno CHAR(4),  --先修课
Ccredit SMALLINT,  --学分
CONSTRAINT FK_Cpno FOREIGN KEY (Cpno) REFERENCES Course(Cno)  --建表时添加外键
);


--建立学生选课表
CREATE TABLE SC
(Sno CHAR(9),
Cno CHAR(4),
Grade SMALLINT, --成绩
PRIMARY KEY (Sno,Cno)
);


添加或者删除约束

--添加外键
ALTER TABLE SC ADD CONSTRAINT FK_Cno FOREIGN KEY (Cno) REFERENCES Course(Cno);
ALTER TABLE SC ADD CONSTRAINT FK_Sno FOREIGN KEY (Sno) REFERENCES Student(Sno);
ALTER TABLE SC ADD CONSTRAINT FK_test FOREIGN KEY (Sno) REFERENCES Course(Cno);

--删除外键
ALTER TABLE Course DROP CONSTRAINT FK_test;


删除表的操作

--删除表
DROP TABLE Student CASCADE CONSTRAINT;
DROP TABLE Course CASCADE CONSTRAINT;
DROP TABLE SC CASCADE CONSTRAINT; 


对已经建好的表进行修改

--向学生表添加“入学时间”列
ALTER TABLE Student ADD S_entrance DATE;

--删除列
ALTER TABLE Student DROP COLUMN S_entrance;

--修改列名
ALTER TABLE Student RENAME COLUMN Ssage TO Sage;

--将年龄类型改为INT
ALTER TABLE Student MODIFY (Sage INT);


插入操作

--插入数据
INSERT INTO Student VALUES ('200215121','李勇','男',20,'CS');
INSERT INTO Student VALUES ('200215122','刘晨','女',19,'CS');
INSERT INTO Student VALUES ('200215123','王敏','女',18,'MA');
INSERT INTO Student VALUES ('200215125','张立','男',19,'IS');

INSERT INTO Course VALUES ('6','数据处理',null,2);
INSERT INTO Course VALUES ('4','操作系统','6',3);
INSERT INTO Course VALUES ('7','PASCAL语言','6',4);
INSERT INTO Course VALUES ('5','数据结构','7',4);
INSERT INTO Course VALUES ('1','数据库','5',4);
INSERT INTO Course VALUES ('3','信息系统','1',4);
INSERT INTO Course VALUES ('2','数学',null,2);

INSERT INTO SC VALUES ('200215121','1',92);
INSERT INTO SC VALUES ('200215121','2',85);
INSERT INTO SC VALUES ('200215121','3',88);
INSERT INTO SC VALUES ('200215122','2',90);
INSERT INTO SC VALUES ('200215122','1',80);

--插入子查询结果
CREATE TABLE Dept_age
(Sdept CHAR(20),
AVG_age REAL);

INSERT INTO Dept_age (Sdept,AVG_age) SELECT Sdept , AVG(Sage) FROM Student GROUP BY Sdept;


索引,提高查询效率

--建立索引
CREATE UNIQUE INDEX Stusno ON Student(Sno DESC);
CREATE UNIQUE INDEX Coucno ON Course(Cno DESC);
CREATE UNIQUE INDEX SCno ON SC (Sno ASC,Cno DESC);

--删除索引
DROP INDEX SCno;


查询操作,变化多样

--查询经过计算的列,可以起别名(AS可省略)
SELECT Sname,2004-Sage BIRTHDAY FROM Student;


--可以查询字符串常量和函数
SELECT Sname NAME , 'Year of Birth:' BIRTH , 2004-Sage BIRTHDAY , LOWER(Sdept) DEPARTMENT FROM Student;


--消除取值重复的行,缺省为ALL
SELECT DISTINCT Sno FROM SC;
 
--比较大小,>=、<=、!=、<>、!>、!<
SELECT DISTINCT Sno FROM SC WHERE Grade >= 90;


--确定范围,between 下限 and 上限,相对的是 NOT between 下限 and 上限
SELECT Sname,Sdept,Sage FROM Student WHERE Sage NOT BETWEEN 20 AND 23;


--确定集合,关键词 IN,相对的是NOT IN
SELECT Sname,Ssex FROM Student WHERE Sdept  IN ('IS','MA','CS');


--字符匹配,[NOT] LIKE '匹配字符串' [ESCAPE '换吗字符']
UPDATE Student SET Sname = '李勇%' WHERE Sname = '李勇';
SELECT * FROM Student WHERE Sname LIKE '%\%%'ESCAPE '\';  --反斜杠后的%被转义,%不在具有通配符的含义
UPDATE Student SET Sname = '李勇' WHERE Sname = '李勇%';


--涉及空值查询,IS [NOT] NULL
SELECT * FROM Course WHERE Cpno IS NULL;


--多重条件查询 AND OR
SELECT * FROM Student WHERE Sdept = 'IS' OR Sdept = 'CS' OR Sdept = 'MA';


--ORDER BY 子句,ASC  DESC
SELECT * FROM Student ORDER BY Sdept,Sage DESC;
SELECT * FROM Course ORDER BY Cname;  --ORDER BY 字符字段


--聚集函数 COUNT(),MAX(),MIN(),AVG(),SUM(),注意:聚集函数不能作为WHERE的条件表达式
SELECT COUNT(Cpno) FROM Course;
SELECT COUNT(*) FROM Course;
SELECT AVG(Grade) FROM SC WHERE Cno = 2;


--GROUP BY 字句
SELECT Cno , COUNT(Sno) NUM FROM SC GROUP BY Cno;
SELECT Sno FROM SC GROUP BY Sno HAVING COUNT(Cno) >= 2;  --HAVING作用于GROUP BY的分组,WHERE作用于基本表或试图,聚集函数可以作用于HAVING


--等值与非等值连接查询
SELECT a.*,b.* FROM Student a , SC b WHERE a.Sno = b.Sno;  --等值连接
SELECT Student.* FROM Student , SC WHERE Student.Sno = SC.Sno AND Cno = '2' AND Grade > 70;
SELECT a.* , b.* ,c.* FROM Student a , SC b , Course c WHERE a.sno = b.sno AND b.cno = c.cno;
SELECT a.* , b.* FROM Student a INNER JOIN SC b ON a.Sno = b.Sno; --内连接


--自身连接
SELECT a.Cno , b.Cpno 间接先修课 FROM Course a , Course b WHERE a.Cpno = b.Cno ORDER BY a.Cno;


--外连接
SELECT a.* , b.* FROM Student a LEFT JOIN SC b ON a.Sno = b.Sno;
SELECT a.* , b.* FROM Student a RIGHT JOIN SC b ON a.Sno = b.Sno;
SELECT a.* , b.* FROM Student a FULL JOIN SC b ON a.Sno = b.Sno;


--嵌套查询,注意:子查询SELECT不允许用ORDER BY子句
SELECT * FROM Student WHERE Sno IN (SELECT Sno FROM SC WHERE Cno = '2');
SELECT * FROM Student WHERE Sdept IN (SELECT Sdept FROM Student WHERE Sname = '刘晨'); --不相关子查询,子查询的查询条件不依赖于父查询
SELECT * FROM Student WHERE Sdept = (SELECT Sdept FROM Student WHERE Sname = '刘晨');  --子查询结果是单值,所以可以用等号。注意只有当子查询是单值时才可以用比较运算符
SELECT * FROM Student WHERE  (SELECT Sdept FROM Student WHERE Sname = '刘晨') = Sdept ;
SELECT a.* FROM Student a , Student b WHERE b.Sname = '刘晨' AND a.Sdept = b.Sdept; --和上面三条等价
SELECT DISTINCT a.Sno , Sname FROM Student a , SC b WHERE a.Sno IN (SELECT Sno FROM SC , Course WHERE SC.Cno = Course.Cno AND Cname = '信息系统');
SELECT DISTINCT Sno , Sname FROM Student WHERE Sno IN (SELECT Sno FROM SC WHERE Cno IN (SELECT Cno FROM Course WHERE Cname = '信息系统'));
SELECT DISTINCT a.Sno , Sname FROM Student a , SC b , Course c WHERE Cname = '信息系统' AND c.Cno = b.Cno AND b.Sno = a.Sno; --和上面两条等价
SELECT a.* , Cno FROM Student a , SC b WHERE Grade > (SELECT AVG(Grade) FROM SC WHERE  a.Sno = b.Sno); -- 相关子查询
SELECT Sno , Cno FROM SC a WHERE Grade > (SELECT AVG(Grade) FROM SC b WHERE a.Sno = b.Sno); -- 相关子查询


--带ANY(SOME) , ALL 谓词的子查询,
SELECT Sname , Sage FROM Student WHERE Sage < ANY (SELECT Sage FROM Student WHERE Sdept = 'CS') AND Sdept != 'CS'; --ANY 也可以用 SOME 代替
SELECT Sname , Sage FROM Student WHERE Sage <  (SELECT MAX(Sage) FROM Student WHERE Sdept = 'CS') AND Sdept != 'CS';--和上面一条等价,注意:用聚集函数查询比用ANY或ALL效率高
SELECT Sname , Sage FROM Student WHERE Sage < ALL (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'; --和上面一条等价


--带有EXISTS 或 NOT EXISTS 谓词的子查询,不返回任何数据只产生 TRUE 或者 FALSE ,注意:某些带 [NOT] EXISTS不能被其他姓氏子查询代替,但所有带IN ,比较运算符,ANY或ALL的子查询都能被EXISTS查询代替
SELECT Sname FROM Student  WHERE EXISTS (SELECT * FROM SC WHERE SC.Sno = Student.Sno AND Cno = '1'); --由EXISTS 引出的查询通常都用 *
SELECT Sname FROM Student a , SC b WHERE a.Sno = b.Sno AND b.Cno = '1'; --和上面一条等价
SELECT Sname FROM Student  WHERE NOT EXISTS (SELECT * FROM SC WHERE SC.Sno = Student.Sno AND Cno = '1');
SELECT * FROM Student S1 WHERE  EXISTS (SELECT * FROM Student S2 WHERE S1.Sdept = S2.Sdept AND Sname = '刘晨'); --和 139 行等价
SELECT * FROM Student WHERE NOT EXISTS (SELECT * FROM Course WHERE NOT EXISTS (SELECT * FROM SC WHERE Student.Sno = Sno AND Course.Cno = Cno)); --查询选修了全部课程的学生,NOT EXISTS相当于 任意
SELECT * FROM Student x WHERE NOT EXISTS (SELECT Cno FROM SC y WHERE Sno = '200215122' AND NOT EXISTS (SELECT * FROM SC z WHERE y.Cno = z.Cno AND x.Sno = z.Sno)); 


--集合查询,并UNION ,交INTERSECT ,差 MINUS ,注意:参加集合操作的查询结果列数必须相同,对应项类型也必须相同
SELECT * FROM Student WHERE Sdept = 'CS' UNION SELECT * FROM Student WHERE Sage <= 19; --并集,UNION会自动去掉重复行,保留要用UNION ALL
SELECT * FROM Student WHERE Sdept = 'CS' INTERSECT SELECT * FROM Student WHERE Sage <= 19; --交集
SELECT * FROM Student WHERE Sdept = 'CS' AND Sage <= 19; --和上面一条等价
SELECT * FROM Student WHERE Sdept = 'CS' MINUS SELECT * FROM Student WHERE Sage <= 19; --差集
SELECT Sno FROM  SC WHERE Cno = '1' UNION SELECT Sno FROM SC WHERE Cno = '2';

以上查询操作的结果集请读者自行操作


修改和删除操作

--修改数据
UPDATE Student SET Sage = Sage + 1;
UPDATE SC SET Grade = Grade + 1 WHERE SC.Sno = Student.Sno AND Student.Sdept = 'CS'; --错误
UPDATE SC SET Grade = Grade + 1 WHERE (SELECT Sdept FROM Student WHERE Student.Sno = SC.Sno) =  'CS'; --计算机系全体学生成绩加一,带子查询的修改语句

--删除数据
DELETE FROM Student WHERE Sno = '200215128';
DELETE FROM SC WHERE (SELECT Sdept  FROM Student WHERE Sno = SC.Sno) = 'CS'; --带子查询的删除语句


视图

--定义视图,SELECT 语句中不能有ORDER BY 和 DISTINCT
CREATE VIEW IS_Student1 AS SELECT Sno IS_Sno , Sname , Sage FROM Student WHERE Sdept = 'IS';  --行列子集视图,视图列默认为SELECT子句的列,当多表查询时列名重合或者聚集函数或者列表达式作为列名则需要视图自己定义列
CREATE VIEW IS_Student2 (Sno , Sname , Ssex , Ssage ,Sdept) AS SELECT * FROM Student WHERE Sdept = 'IS' WITH CHECK OPTION; --表示对视图进行增删改时的操作行要满足子查询中的条件表达式
CREATE VIEW IS_Student3 AS SELECT IS_Student1.IS_Sno , Sname , Sage FROM IS_Student1 , SC WHERE IS_Student1.IS_Sno = SC.Sno AND Cno = '1'; --在试图上再导出视图
CREATE VIEW S_G (Sno ,Sname , AVG_Grade) AS SELECT SC.Sno , Sname , AVG(Grade) FROM SC , Student WHERE Student.Sno = SC.Sno GROUP BY SC.Sno , Sname; --分组视图,PS:可以GROUP BY多列 
CREATE VIEW Girl AS SELECT Sno , Sname Name , Sage GirlAge FROM Student WHERE Ssex = '女' WITH CHECK OPTION; --修改基本表Student后会破坏基本表与该视图的映像关系,改表之后需删掉视图重建


--删除视图, CASCADE则该视图导出的视图一起删除
DROP VIEW S_g;

--查询视图
SELECT * FROM IS_Student1 WHERE Sage < 22;  --视图消解,将视图中的子查询和用户查询结合起来 WHERE Sdept = 'IS' AND Sage < 22
SELECT * FROM S_G WHERE AVG_Grade <= 90;

--更新视图
UPDATE IS_Student1 SET Sname = '刘辰' WHERE Sname = '刘晨';
INSERT INTO IS_Student2 VALUES ('200215129' , '王杰' , '男' , '19' , 'IS');  --Sdept必须为IS
UPDATE S_G SET S_G = 70 WHERE Sno = '200215121'; --错误,因为平均成绩不能更新,所以并不是所有视图都可以更新,一般行列子集视图是可以更新的

 

你可能感兴趣的:(PL/SQL入门——基础的增删改查)