小蝦米原創作品,轉載請注明出處:https://www.cnblogs.com/shrimp-can/p/9898735.html
小蝦米最近在找工作,筆試題少不了SQL語句,幾年沒有碰過數據庫都忘記了,復習了一下,將常用的簡單的SQL語句以例子的形式系統的整理一下。
此文章根據書《數據庫系統概念》第三章整理而成。
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
貫穿整個例子的關系有如下5個,最前面是關系名字,‘:’后面是該關系的屬性
1.建築department:系名dept_name, 建築building, 預算budget
2.課程course:課程號course_id,課程名稱title,課程所屬的系名dept_name,學分credits
3.教師信息instructor:教師號ID,教師名字name,教師所在的系dept_name,薪資salary
4.開課信息section:課程號course_id,課程段標識sec_id,學期semester,年份year,課程所在建築building,課程所在教室號room_number,時間檔序號time_slot_id
5.教學信息teaches:教室號ID,課程號course_id,課程信息序號sec_id,學期semester,年份year
6.選課信息takes:學生學號ID,課程標識course_id,課程段標識sec_id,學期semester,年份year,成績grade
7.學生信息student:學生學號ID,學生姓名name,學生所在系dept_name,總學分tot_cred
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
一、關系的創建與刪除create、delete
1.表的創建create table
例1.1:創建一個department關系
create table department
(dept_name varchar(20),
building varchar(15),
budget numeric(12,2),
primary key (dept_name)); //主碼
2.表的刪除drop table
例1.2:刪除關系department
drop table department;
二、單關系簡單查詢select
1.基本的單關系查詢
例2.1:找出所有教師的名字
select name from instructor;
例2.2:找出所有教師所在的系名
select dept_name from instructor;
注:因為instructor關系中多個老師可以在一個系中,所以上述查詢結果中會有重復的系名
2.去除重復distinct
例2.3:找出所有教師所在的系名,去除重復
select distinct dept_name from instructor;
3.顯式指明不去除重復all
例2.4:例2中指明不去除重復
select all dept_name from instructor;
4.算數表達式+、-、*、/運算
例2.5:將教師的薪資增長10%
select ID, name, dept_name, salary*1.1 from instructor;
5.where子句
選出滿足特定條件的元組,可以使用邏輯連詞and、or 和not。可以使用運算符<、<=、>、>=、=和<>
例2.6:找出所有在Comuter Science系並且工資超過70000美元的教師的姓名
select name from instructor where dept_name='Computer Science' and salary>70000;
三、多關系簡單查詢
1.簡單查詢
例3.1:找出所有教師的姓名,以及他們所在系的名稱和系所在建築的名稱
select name, instructor.dept_name, building from instructor, department where instructor.dept_name=department.dept_name;
例3.2:找出Computer Science系的教師名和課程標識
select name, course_id from instructor, teaches where instructor.ID=teaches.ID and dept_name='Computer Science';
2.自然連接natural join
自然連接作用於兩個關系,並產生一個關系作為結果,只考慮在關系模式中出現相同屬性的取值相同的情況
例3.3:例2可以用自然連接改為
select name, course_id from instructor natural join teaches;
例3.4:列出教師的名字和他們所講授的課程的名稱
select name, title from instructor natural join teaches, course where course.course_id=teaches_course_id;
3.連接中指定哪些列相等join...using
例3.5:例4可以改為
select name, title from (instructor natural join teaches) join course using (course_id);
四、基本運算
1.更名運算as
例4.1:對於所有講授課程的教師,找出他們的姓名以及所講授的課程標識,將查找結果的教師名字改為instructor_name
select name as instructor_name, course_id from instructor, teaches where instructor.ID=teaches.ID;
例4.2:將例1中的instructor關系和teaches關系重新命名為T和S
select T.name, S.course_id from instructor as T, teaches as S where T.ID=S.ID
例4.3:找出滿足下面條件的所有教師的姓名,他們的工資至少比Biology系某一個教師的工資要高(去除重復的教師姓名)
select distinct T.name from instructor as T, instructor as S where T.salary>S.salary and S.dept_name='Biology';
2.字符串運算
2.1.字符串匹配like %/_
%:匹配任意字符串
_:匹配任意一個字符
如
Intro%:匹配任意以"Intro"開頭的字符串
%Comp%:匹配任意包含"Comp"子串的字符串
_ _ _:匹配只含有三個字符的字符串
_ _ _%:匹配至少含有三個字符的字符串
例4.4:找出所在建築名稱中包含子串‘Watson’的所有系名
select dept_name from department where building like '%Watson%';
2.2.轉義字符的處理escape '\'
like 'ab\%cd%' escape '\':匹配所有以'ab%cd'開頭的字符串
like 'ab\\cd%' escape '\':匹配所有以ab\cd開頭的字符串
3.select中選擇所有的屬性*
例4.5:找出所有講授了課程的教師信息
select instructor.* from instructor, teaches where instructor.ID=teaches.ID;
4.排列查詢結果中元組的顯示次序order by
order by默認升序,desc表示降序,asc表示升序
例4.6:按字母順序列出Physics系的所有教師名字
select name from instructor where dept_name='Physics' order by name;
例4.7:按salary的降序列出整個instrutor關系,如果幾位教師的工資相同,就按他們的名字升序排列
select * from instructor order by salary desc, name asc;
5.where子句的謂詞between... and...
例4.8:找出工資在90000美元和100000美元之間的教師的姓名
select name from instructor where salary between 90000 and 100000;
它與此SQL語句等價
select name from instructor where salary>=90000 and salary<=100000;
例4.9:查找Biology系講授了課程的所有教師的姓名和他們所講授的課程標識
select name, course_id from instructor and teaches where (instructor.ID, dept_name)=(teaches.ID, 'Biology');
它與下面的SQL語句等價
select name, course_id from instructor and teaches where instructor.ID=teaches.ID and dept_name='Biology';
五、集合運算
1.並運算union
union會自動去除重復,要想保留所有的重復信息,用union all替代union
例5.1:找出在2009年秋季開課或者在2010年春季開課或者兩個學期都開課的所有課程標識
(select course_id from section where year=2009 and semester='Fall') union
(select course_id from section where year=2010 and semester='Spring');
2.交運算intersect
intersect也會自動去除重復,要想保留所有的重復,用intersect all替代intersect
例5.2:找出在2009年秋季和2010年春季同時開課的所有課程序號的集合
(select course_id from section where year=2009 and semester='Fall') intersect
(select course_id from section where year=2010 and semester='Spring');
3.差運算except
將會在第一個關系中減去所有在關系2中出現的元祖,最后的結果將不會有重復的元組出現。如果想保留重復,用except all替代except
例5.3:找出在2009年秋季開課但不在2010年春季開課的所有課程序號
(select course_id from section where year=2009 and semester='Fall') except
(select course_id from section where year=2010 and semester='Spring');
六、聚集函數
1.基本聚集
平均值:avg
最小值:min
最大值:max
總和:sum
計數:count
例6.1:找出Computer Science系教師的平均工資
select avy(salary) from instructor where dept_name='Comouter Science';
例6.2:例1中給平均工資賦個新名稱avg_salary
select avy(salary) as avg_salary from instructor where dept_name='Comouter Science';
例6.3:找出在2010年春季學期講授課程的教師總數
select count (distinct ID) from teaches where semester='Spring' and year=2010;
注意:一個教師可能講授幾個課程段,但是在這里只應被計算一次,因此需要去除重復
例6.4:計算課程信息關系中的元祖個數
select count (*) from course;
2.分組聚集group by
group by將在該屬性取值相同的元組划分為一組
例6.5:找出每個系的平均工資
select avy(salary) from instructor group by dept_name;
例6.6:找出每個系在2010年春季講授了課程的教師人數
select dept_name, count(distinct ID) from teaches natural join instructor where semester='Spring' and year=2010 group by dept_name;
3.having子句
對group by子句構成的分組限定條件
例6.7:找出教師平均工資超過42000美元的系
select dept_name, avg(salary) as avg_salary from instructor group by dept_name having avg(salary)>42000;
例6.8:對於在2009年講授的每個課程段,如果該課程段有至少2名學生選課,找出選修該課程段的所有學生的總學分的平均值
select course_id, year, semester, sec_id, avg(tot_cred) from takes natural join student group by course_id, sec_id, semester, year having count(ID)>=2;
七、嵌套子查詢
1.集合成員的資格in, not in
例7.1:找出在2009年秋季開課,同時也在2010年春季開課的所有課程
select distinct course_id from section where semester='Fall' and year=2009 and course_id in
(select course_id from section where semester='Spring' and year=2010);
例7.2:找出在2009年秋季開課,但是不在2010年春季開課的所有課程
select distinct course_id from section where semester='Fall' and year=2009 and course_id not in
(select course_id from section where semester='Spring' and year=2010);
例7.3:查找既不叫‘Mpzart’也不叫'Einstein'的教師姓名
select distinct name from instructor where name not in ('Mozart', 'Einstein');
例7.4:找出不同的學生總數,他們選修了ID為10101的教師所講授的課程
select count(sidtinct ID) from takes where course_id, sec_id, semester, year in (select course_id, sec_id, semester, year from teaches where teaches.ID=10101);
2.集合的比較
至少比某一個要大:>some
此外還有:<some,<=some,>=some,=some(等價於in),<>some
比所有的都大:>all
此外還有:<all,<=all,>=all,=all,<>all(等價於not in)
例7.5:找出滿足下面條件的所有教師的姓名,他們的工資至少比Biology系某一個教師的工資要高
select name from instructor where salary >some (select salary from instructor where dept_name='Biology');
例7.6:找出滿足下面條件的所有教師的姓名,他們的工資比Biology系每個教師的工資都高
select name from instructor where salary >all (select salary from instructor where dept_name='Biology');
例7.7:找出平均工資最高的系
select dept_name from instructor where avg(salary) >=all (select avg(salary) from instructor group by dept_name);
3.空關系測試exists, not exists
關系A包含關系B寫成 not exists (B except A)
例7.8.找出在2009年秋季學期和2010年春季學期同時開課的所有課程標識
select course_id from section as S where year=2009 and semester='Fall' and exists
(select * from section as T where year=2010 and semester='Spring' and S.course_id=T.course_id);
例7.9:找出選修了Biology系開設的所有課程的學生
select S.ID, S.name from student as S where not exists ((select course_id from course where dept_name='Biology') except (select T.course_id from takes as T where S.ID=T.ID));
4.重復元組存在性測試unique, not unique
例7.10:找出所有在2009年最多開設一次的課程
select T.course_id from course as T where unique (select R.course_id from section as R where T.course_id=R.course_id and R.year=2009);
或者
select T.course_id from course as T where 1 >= (select count(R.course_id) from section as R where T.course_id=R.course_id and R.year=2009);
例7.11:找出所有在2009年最少開設兩次的課程
select T.course_id from course as T where not unique (select R.course_id from section as R where T.course_id=R.course_id and R.year=2009);
5.from子句中的子查詢
例7.12:找出系平均工資超過42000美元的那些系中教師的平均工資
select dept_name, avg_salary from (select dept_name, avg(salary) as avg_salary from instructor group by dept_name) where avg_salary > 42000;
例7.13:可以給from子句中的查詢結果關系進行命名,並對其屬性進行命名
select dept_name, avg_salary from (select dept_name, avg(salary) from instructor group by dept_name) as dept_avg (dept_name, avg_salary) where avg_salary > 42000;
例7.14:找出所有系中工資總額最大的系
select dept_name, max(tot_salary) from (select dept_name, sum(salary) from instructor group by dept_name) as dept_total (dept_name, tot_salary);
6.with子句
with子句提供定義臨時關系的方法
例7.15:找出具有最大預算值的系
with max_budget (value) as (select max(budget) from department)
select budget from department, max_budget where departmen.budget=max_budget.value;
例7.16:查找所有工資總額大於所有系平均工資總額的系
with dept_total (dept_name, value) as (select dept_name, sum(salary) from instructor group by dept_name),
dept_total_avg(value) as (select avg(value) from dept_total);
select dept_name from dept_total, dept_total_avg where dept_total.value > dept_total_avg.value;
7.標量子查詢
子查詢出現在返回單個值的表達式能夠出現的任何地方。
例7.17:列出所有的系和他們擁有的教師數
select dept_name, (select count(*) from instructor where department.dept_name=instructor.dept_name) as num_instructors from department;
八、數據庫的修改
1.刪除delete
刪除整個關系前面我們已經講了,用drop table,這里是刪除關系中的元組
例8.1:從instructor關系中刪除與Finance系教師相關的所有元組
delete from instructor where dept_name='Finance';
例8.2:刪除所有工資在13000美元到15000美元之間的教師
delete from instructor where salary between 13000 and 15000;
例8.3:從instructor關系中刪除所有這樣的教師元組,他們在位於Watson大樓的系工作
delete from instructor where dept_name in (select dept_name from department where building='Watson');
例8.4:刪除工資低於大學平均工資的教師記錄
delete from instructor where salary < (select avg(salary) from instructor);
2.插入insert into
例8.5:插入的信息是Comouter Science系開設的名為'Database System'的課程CS-437,它有4個學分
insert into course values('CS-437', 'Database System', 'Computer Science', 4);
例8.6:例5中指定屬性插入
insert into course (course_id, title, dept_name, credits) values('CS-437', 'Database System', 'Computer Science', 4);
例8.7:我們想讓Music系每個修滿144學分的學生成為Music系的教師,其工資為18000美元
insert into instructor select ID, name, dept_name, 18000 from student where dept_name='Music' and tot_cred>=144;
3.更新update
例8.8:將所有教師的工資增長5%
update instructor set salary=salary*1.05;
例8.9:給工資低於70000美元的教師工資增長5%
update instructor set salary=salary*1.05 where salary<70000;
例8.10:對工資低於平均數的教師漲5%的工資
update instructor set salary=salary*1.05 where salary<(select avg(salary) from instructor);
例8.11:給工資超過100000美元的教師漲3%的工資,其余教師漲5%
update instructor set salary=salary*1.03 where salary>100000;
update instructor set salary=salary*1.05 where salary<=100000;
例8.12:將例11用case結構
update instructor
set salary = case
when salary <=100000 then salary*1.05
else salary*1.03
end
例8.13:把每個student元組的tot_cred屬性值設為該學生成功學完的課程學分的總和;假設學生在某門課程上的成績既不是'F'也不是空,那么他成功學完了這門課程
update student set tot_cred = (select sum(credits) from takes natural join course where student.ID=takes.ID and takes.grade <>'F' and takes.grade is not null);