數據庫 基本操作總結(上):數據定義、數據操縱、數據查詢

以下操作均在Oracle數據庫下運行,在某些地方的語法可能與MySQL不同。
另外,是否區分大小寫也有不同。(MySQL與Oracle的大小寫問題

SQL語言集數據定義、數據操縱、數據查詢、數據控制功能於一體。
數據定義:create,drop,alter
數據操縱:增(insert into … ),刪(delete from …),改(update … set …)
數據查詢:select
數據控制:grant(授予權限),revoke(收回權限)

本文將介紹數據定義、數據操縱、數據查詢在Oracle數據庫下的基本語法(數據控制的語法詳見此文)。

一、數據定義(create,alter,drop)

1.建立基本表
創建教材中的學生表(Student)、學生選課表(SC)、課程表(Course)
(1)學生表:Student (Sno,Sname,Sage,Ssex,Sdept),其中學號Sno爲主碼。

create table Student
(
    Sno number primary key,
    Sname varchar2(10),
    Sage int,
    Ssex char(2),
    Sdept varchar2(10)
);

(2)課程表:Course (Cno, Cname, Cpno, Ccredit)其中課程號Cno主碼;先行課爲外碼參照Course表中Cno字段。

create table Course
(
    Cno number primary key,
    Cname varchar2(10),
    Cpno varchar2(10) references Course(Cno),
    Ccredit int
);

(3)學生選課表:SC(Sno, Cno, Grade)其中學號Sno、課程號Cno爲主碼;Sno爲外碼參照Student表中Sno字段;Cno爲外碼參照Course表中Cno字段。

create table SC
(
    Sno number references Student(Sno),
    Cno number references Course(Cno),
    Grade int,
    primary key (Sno,Cno)
);

2.修改基本表
(1)在Student表中加入屬性BloodType【char(2)型】。

alter table Student add BloodType char(2);

(2)修改表Student中的Sdept屬性的數據類型爲varchar2(40),注意和定義表的時候類型不同。

alter table Student modify Sdept varchar2(40);

(3)給表Student的sage列添加一個自定義約束,sage必須大於15且小於30。

alter table Student add constraint age_ck check(Sage>15 and Sage<30);

(4)刪除(3)中新添加的約束。

alter table Student drop constraint age_ck;

(5)SC表中的sno增加外鍵約束f_sno,參照Student表中的sno字段。

alter table sc add constraint f_sno foreign key (sno) references student(sno);

(6)刪除表Student中的字段BloodType。

alter table Student drop (BloodType);   #記得加括號,不加括號就要在drop前面寫column

3.刪除基本表
(1)刪除基本表Student。

drop table Student;

(2)刪除基本表SC。

drop table SC;

4.索引操作
(1)在SC表上建立關於Sno升序、Cno降序的唯一索引i_sc+學號後四位。

create unique index i_sc on SC(Sno asc,Cno desc,substr(Sno,-4));

(2)刪除Course表上的索引i_sc。

drop index i_sc;

二、數據操縱(insert,update,delete)

1.插入數據
1)向Student表中插入數據
2)向Course表中插入數據
3)向SC表中插入數據
可參考如下數據,也可不參考。
在這裏插入圖片描述

insert into STUDENT(SNO,SNAME,SSEX,SAGE,SDEPT) values(200215121,'李勇','男',20,'CS');
insert into STUDENT(SNO,SNAME,SSEX,SAGE,SDEPT) values(200215122,'劉晨','女',19,'CS');
insert into STUDENT(SNO,SNAME,SSEX,SAGE,SDEPT) values(200215123,'王敏','女',18,'MA');
insert into STUDENT(SNO,SNAME,SSEX,SAGE,SDEPT) values(200215125,'張立','男',19,'IS');

# 記得先把COURSE表中的外鍵約束關了,否則數據插不進去
insert into COURSE(CNO,CNAME,CPNO,CCREDIT) values(1,'數據庫',5,4);
insert into COURSE(CNO,CNAME,CPNO,CCREDIT) values(2,'數學',null,2);
insert into COURSE(CNO,CNAME,CPNO,CCREDIT) values(3,'信息系統',1,4);
insert into COURSE(CNO,CNAME,CPNO,CCREDIT) values(4,'操作系統',6,3);
insert into COURSE(CNO,CNAME,CPNO,CCREDIT) values(5,'數據結構',7,4);
insert into COURSE(CNO,CNAME,CPNO,CCREDIT) values(6,'數據處理',null,2);
insert into COURSE(CNO,CNAME,CPNO,CCREDIT) values(7,'PASCAL語言',6,4);

insert into SC(SNO,CNO,GRADE) values(200215121,1,92);
insert into SC(SNO,CNO,GRADE) values(200215121,2,85);
insert into SC(SNO,CNO,GRADE) values(200215121,3,88);
insert into SC(SNO,CNO,GRADE) values(200215122,4,90);
insert into SC(SNO,CNO,GRADE) values(200215122,3,80);

2.修改數據
1)將王敏的同學的年齡改爲20。

update STUDENT set sage=20 where sname='王敏';

2)將全部同學的年齡加1。

update STUDENT set sage=sage+1;

3)將’CS’系同學的選課信息中的成績置0。

update SC set grade=0 where sno in 
(
    select sc.sno from STUDENT join SC on(student.sno=sc.sno)
    where sdept='CS'
);

3.刪除數據
1)刪除和’劉晨’在同一個系的學生的信息。(包括劉晨自己也會被刪除)

delete from STUDENT where sdept in
(
    select sdept from STUDENT
    where sname='劉晨'
);

然後發現刪除不了,因爲有外鍵約束,SC表依賴當前表的SNO,
所以要先刪掉SC表中SNO的外鍵約束alter table sc drop constraint SYS_C0051208;
再執行刪除語句即可。

2)刪除’CS’系同學的選課信息。

delete from SC where sno in
(
    select sno from STUDENT
    where sdept='CS'
);

三、數據查詢(select)

1.包括排序、分組的單表查詢
(1)求數學系學生的學號和姓名。

select sno,sname from student where sdept='MA';

(2)求選修了課程的學生學號。

# 學號distinct去重,因爲SC表中學號可以重複,一個學號可選多門課
select distinct sno from sc; 

(3)求選修課程號爲‘2’的學生號和成績,並要求對查詢結果按成績的降序排列,如果成績相同按學號的升序排列。

select sno,grade from sc where cno=2 order by grade DESC,sno ASC;

(4)求選修課程號爲’2’且成績在80~90之間的學生學號和成績,並將成績乘以0.8輸出。

select sno,grade*0.8 from sc where cno=2 and grade>=80 and grade<=90;

(5)求數學系或計算機系姓張的學生的信息。

# 注意and的優先級高於or,加一個括號即可
select * from student where sname like '張%' and (sdept='MA' or sdept='CS');

(6)求缺少了成績的學生的學號和課程號。

select sno,cno from sc where grade is null;

(7)查詢各個課程號與相應的選課人數。

select cno,count(*) from sc group by cno;

2.多表連接查詢
(1)查詢每個學生的情況以及他所選修的課程。

select student.sno,sname,ssex,sdept,cno from student,sc where student.sno=sc.sno;

(2)求學生的學號、姓名、選修的課程及成績。

select student.sno,sname,cno,grade from student,sc where student.sno=sc.sno;

(3)求選修課程號爲‘1’且成績在90分以上的學生學號、姓名和成績。

select student.sno,sname,grade from student,sc where student.sno=sc.sno and cno=1 and grade>=90;

(4)查詢每一門課程的間接先行課。

select c1.cno,c2.cpno from course c1,course c2 where c1.cpno=s2.cno;

(5)查詢與’劉晨’在同一個系學習的學生。

select s1.sno,s1.sname,s1.sage,s1.ssex,s1.sdept 
from student s1,student s2 
where s1.sdept=s2.sdept and s2.sname='劉晨'; #兩個相同的表通過sdept連接

(6)查詢選修了課程名爲‘信息系統‘的學生學號和姓名。

select sc.sno,sname from student,sc,course 
where student.sno=sc.sno and sc.cno=course.cno and cname='信息系統'; 

(7)查詢平均成績在80分以上的學生學號和平均成績。

select sno,avg(grade) from sc group by sno having avg(grade)>=80;

(8)查詢選修了1門以上課程的學生的學號。

select sno from sc group by sno having count(*)>1;

3.嵌套查詢
(1)求選修了信息系統的學號和姓名。

select sno,sname from student where sno in
(
    select sno from sc where cno in 
    (
        select cno from course 
        where cname='信息系統'
    )
);

(2)查詢與劉晨在同一個系學習的學生。

select * from student where sdept in
(
	select sdept from student 
	where sname='劉晨'
);

(3)求選修1號課程的成績高於劉晨的成績(指劉晨選修的所有的課程的成績)的學生學號及成績。

select sno,grade from sc where cno=1 and grade >
(
    select max(grade) from sc where sno in
    (
        select sno from student
        where sname='劉晨'
    )
);

(4)求其他系中比計算機系某一學生年齡小的學生(即年齡小於計算機系年齡最大者的學生)。

select * from student where sage <
(
    select max(sage) from student 
    where sdept='CS'
);

(5)求其他系中比計算機系學生年齡都小的學生姓名及年齡。

select sname,sage from student where sage <
(
    select min(sage) from student 
    where sdept='CS'
);

(6)求選修課程超過2門的學生的學號和姓名。

select sno,sname from student where sno in
(
    select sno from sc
    group by sno having count(*)>2
);

(7)求沒有選修3號課程的學生姓名。

select sname from student where not exists 
(
    select * from sc
    where cno=3 and student.sno=sc.sno
);

(8)查詢選修了全部課程的學生姓名。【重點!】

select sname from student where not exists 
(
    select * from course where not exists
    (
        select * from sc
        where sc.cno=course.cno and sc.sno=student.sno
    )
);

分析:
這個比較難懂,我們先看看內兩層查詢,表示選出當前學號(比如說122)沒選的課

select * from course where not exists
(
    select * from sc
    where sc.cno=course.cno and sc.sno=200215122
); 

如果這個結果是空,表示當前學號(比如說122)沒選的課爲空,最外層加一個select sname from student where not exists,表示選出所有 沒有沒選的課 的學生。

可以將not exists當作“減法”理解,內兩層的意思就是把所有的課減去122學號選的課,如果爲空(所有的課被122選的課給減沒了),那麼就選出122來。

(9)求至少選修了學號爲“200215121”的學生所選修全部課程的學生學號和姓名。【重點!】
分析:
先選出121學生選的課 減去 122學生選的課:

select * from sc sc1 where sno=200215121 and not exists
(
    select * from sc sc2
    where sc1.cno=sc2.cno and sc2.sno=200215122
);

單純的只有where not exist表示選出空的。
以上的整個式子表示減法:最內層用cno連接,表示找選課記錄,然後121選課集合減去122選課集合。

過程的話實際就是兩層for循環遍歷,for(i: 121選課){for (j: 122選課)},對於每個i,判斷122選課中是否存在j滿足i.cno=j.cno,如果有,不爲空,那麼not exists就不選出這個i,實際上這不就相當於當前遍歷到的i的記錄被相同的j減去了嗎!而且外層循環是121選課,說明最終輸出的答案只能是121選課的子集,只要答案爲空我們就把他選出來!

如果爲空,說明122這個學號把121的所有課都選了(所以121的課被減沒了)。
還有一種情況,就是122這個學號不僅把121的所有課都選了,他還選了其他課,這個時候的減法結果不是按“負數”理解,就理解成122把121的所有課都減沒了,他還剩了多餘的課,那是122的選課集合剩了(不是121剩了),最主要的是121被減沒了,所以121的選課集合答案是空。

繞了這麼多,反正核心就是:
找一個學生的選課集合作爲“減數”,如果他大於等於121的選課集合,那麼121的選課集合減去他之後就能變成空,這個“減數”就是我們要找的。

最後,把學號122改成變量,加一個最外層查詢遍歷所有學生,
因爲找到爲空的就要把他選出來,所以最外層寫not exists選出空的,那麼整個答案就是:

select sno,sname from student where not exists
(
    select * from sc sc1 where sno=200215121 and not exists
    (
        select * from sc sc2
        where sc1.cno=sc2.cno and sc2.sno=student.sno
    )
);
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章