《數據庫系統概念》學習筆記——第三章 SQL

Table of Contents

第三章 SQL

3.1 SQL查詢語言概覽

3.2 SQL數據定義

3.2.1 基本類型

3.2.2 基本模式定義

3.3 SQL查詢的基本結構

3.3.1 單關係查詢

3.3.2 多關係查詢

3.3.3 自然連接

3.4 附加的基本運算

3.4.1 更名運算 as

3.4.2 字符串運算

3.4.3 select 子句中的屬性說明

3.4.4 排列元組的顯示次序 order by

3.4.5 where子句謂詞

3.5 集合運算

3.6 空值null

3.7 聚集函數

3.8 嵌套子查詢

3.8.1 集合成員資格:in, not in

3.8.2 集合的比較

3.8.3 空關係測試:exists, not exists

3.8.4 重複元組存在性測試unique

3.8.5 from子句中的子查詢

3.8.6 with子句

3.8.7 標量子查詢scalar subquery

3.9 數據庫的修改

總結:


第三章 SQL

3.1 SQL查詢語言概覽

SQL:結構化查詢語言。最新的SQL標準是2008。

SQL語言包括以下幾個部分:

  • 數據定義語言(DDL):DDL提供定義關係模式、刪除關係、以及修改關係模式的命令。
  • 數據操作語言(DML):DML提供從數據庫中查詢信息,以及在數據庫中插入元組、刪除元組、修改元組的能力。
  • 完整性(integrity):DDL包括定義完整性約束的命令,保存在數據庫中的數據必須滿足所定義的完整性約束。破壞完整性約束的更新是不允許的。
  • 視圖定義(view definition):DDL包括定義視圖的命令。
  • 事務控制(transaction control):SQL包括定義事務的開始和結束的命令。
  • 嵌入式SQL和動態SQL(embedded SQL and dynamic SQL): 嵌入式和動態SQL定義SQL語句如何嵌入到通用編程語言,如C和C++
  • 授權(authorization):DDL包括定義對關係的訪問權限的命令

3.2 SQL數據定義

SQL DDL不僅能夠定義一組關係,還能定義每個關係的信息,包括:

  • 每個關係的模式
  • 每個屬性的取值類型
  • 完整性約束
  • 每個關係維護的索引集合
  • 每個關係的安全性和權限信息
  • 每個關係在磁盤上的物理存儲結構

3.2.1 基本類型

  • char(n): 固定長度的數組。當存入的值不足n位時,自動追加空格。
  • varchar(n): 可變長度的數組,用戶指定最大長度n
  • int
  • smallint:小整數類型
  • numeric(p,d):定點數,精度由用戶指定。這個數有p位數字,其中有d位在小數點右邊。
  • real, double precision: 浮點數與雙精度浮點數,精度與機器有關
  • float(n):精度至少爲n位的浮點數

每種類型都可能包括一個被稱爲空的特殊值。

注意:當比較char和varchar時,是否會自動在varchar類型後面追加空格取決於數據庫的實現。

3.2.2 基本模式定義

  • 創建表:其中Ai是屬性,D1是屬性Ai的域。
    • 常用的完整性約束:
      • primary key(Aj1, Aj2, ..., Ajm): 聲明屬性Aj1, Aj2, ..., Ajm爲關係的主碼。主碼必須非空且唯一。
      • foreign key (Ak1, Ak2,..., Akn) references table_B: 聲明關係中任意元組對Ak1, Ak2,..., Akn上的取值必須對應於關係table_B中某元組在主碼上的取值。
      • not null: 一個屬性上的not null約束表明該屬性上不允許控制。

注意:SQL禁止破壞完整性約束的任何數據庫更新。

create table R ( A1 D1 not null, A2 D2, ..., An Dn, <完整性約束1>, ..., <完整性約束2>);
  • 插入元組:
insert into R (A1, A2, ..., An) values (V1, V2, ..., Vn); insert into R values (V1, V2,..., Vn);
  • 刪除元組:
delete from R; --從表R中刪除全部元組 drop table R; --從數據庫中刪除關係R
  • 修改關係的屬性
alter table R add A D; --給表R添加屬性A,其域爲D alter table R drop A; --刪除表R的屬性A

3.3 SQL查詢的基本結構

SQL查詢的基本結構由三個子句構成:select, from 和where。

3.3.1 單關係查詢

-- 可以包括重複數據 
select A1, A2,.., An from R; 
-- 去除重複 
select distinct A1, A2,.., An from R; 
-- 顯示的不去除重複 
select all A1, A2, ..., An from R; 
-- select子句可以含有+-*/運算符的算術表達式;運算對象可以是常數或元組的屬性。 
select A1, A2, ..., A3 * 1.1 from R; 
-- where子句可以包括邏輯連詞and, or 和not 
-- 邏輯連詞的運算對象可以使包含比較運算符的<, <=, >, >=, = 和<>的表達式 
select A1, A2, ... An from R where A1=V1 and A2=V2;

3.3.2 多關係查詢

SQL查詢的基本結構由三個子句構成:select, from 和where子句構成:

  • select子句:列出查詢結果中所需要的屬性
  • from子句:一個查詢求值中需要訪問的關係列表
  • where子句:一個作用在from子句中關係的屬性上的謂詞

執行順序:from->where->select。

在SQL的實際實現中,它會通過儘可能只產生滿足where子句謂詞的笛卡爾積元素來進行優化執行。如果省略where子句,則會輸出笛卡爾積。

3.3.3 自然連接

笛卡爾積:它將第一個關係的每個元組與第二個關係的所有元組都進行連接。

自然連接:只考慮連接在兩個關係上都出現的屬性上取值相同的元組對。

-- 在R1和R2上都有的屬性做連接 
select A1, A2,...,An from R1 natrual join R2; 

-- 在僅在A1和A2屬性連接R1和R2 - 自然連接的一種形式 
-- 相當於 select A1, A2,...,An from R1, R2 where R1.A1=R2.A1 and R1.A2 = R2.A2; 
select A1, A2,...,An from R1 join R2 using (A1, A2);

例如:
 

select name, course_id from instructor, teaches where instructor.ID = teaches.ID; 
--可以簡寫爲: 
select name, course_id from instructor natural join teaches;

3.4 附加的基本運算

3.4.1 更名運算 as

oldname as newname 
-- 找出滿足下麪條件的所有教師的姓名,他們的工資至少比Biology系的某一個教師的工資要高 
select distinct T.name from instructor as T, instructor as B where T.salary>S.salary and S.dept_name = 'Biology'; 
/*其中T和S 被稱作相關名稱(correlation name)/表別名(table alias)/相關變量(correlation variable)/元組變量(tuple variable)*/

3.4.2 字符串運算

字符串上可以使用的常見函數:

  • upper(s):將字符串s轉爲大寫
  • lower(s):將字符串s轉爲小寫
  • trim(s): 去掉字符串後面的空格

在字符串上使用like操作符實現模式匹配:

  • 百分號(%): 匹配任意字符
  • 下劃線(_): 匹配任意一個字符

模式是大小寫敏感的。

'Intro%' - 匹配“Intro”打頭的字符串 
'%Comp%' - 匹配任何包括“Comp”子串的字符串 
'___' - 匹配只含三個字符的字符串 
'___%' - 匹配至少包含三個字符的字符串 

// 可以使用escape關鍵字來定義轉義符 like 'ab\%cd%' escape 
'\' - 匹配以“ab%cd”開頭的字符串

3.4.3 select 子句中的屬性說明

select R.* from R;

3.4.4 排列元組的顯示次序 order by

order by 默認使用升序排列,asc表示升序,desc表示降序

select * from R order by A1; select * from instructor order by salary desc, name asc;

3.4.5 where子句謂詞

  • between, not between關鍵字
select name from instructor where salary between 90000 and 100000;
  • 在元組上使用比較運算符, 那麼會按照字典順序進行比較
select name, course_id from instructor, teaches where instructor.ID= teaches.ID and dept_name = "Biology"; 
--可以重寫爲: 
select name, course_id from instructor, teaches where (instructor.ID, dept_name) = (teaches.ID, 'Biology');

3.5 集合運算

  • 並運算union、union all: 與select子句不同,union運算會自動去除重複;若想保留重複,需要使用union all
(select course_id from section where semester = "Fall" and year = 2019) union (select course_id from section where semester = "Spring" and year = 2020)
  • 交運算intersect、intersect all: intersect運算也會自動去除重複
(select course_id from section where semester = "Fall" and year = 2019) intersect (select course_id from section where semester = "Spring" and year = 2020)
  • 差運算except、except all: except運算也會自動去除重複
(select course_id from section where semester = "Fall" and year = 2019) except (select course_id from section where semester = "Spring" and year = 2020)

3.6 空值null

空值運算規則:

  • 如果算數表達式(+-*/)的任意輸入爲空,則該算數表達式結果爲空
  • 涉及空值的任何比較運算的結果視爲unknown(既不是謂詞is null, 也不是is not null),是true和false之外的第三個邏輯值

擴展到unknown的布爾運算:

  • and:
    • true and unknown ===> unknown
    • false and unknown ===> false
    • unknown and unknown ===> unknown
  • or:
    • true or unknown ===> true
    • false or unknown ===> unknown
    • unknown or unknown ===> unknown
  • not
    • not unknown ==> unknown

注意:

select distinct會去除重複元組。在該過程中,需要比較兩個元組的對應的屬性值。如果兩個值都是非空並且值相等,或者都爲空,那麼它們是相同的。

但是這與謂詞對待空值的方式不同,謂詞中null = null 會返回unknown,而不是true。

3.7 聚集函數

聚集函數是以值的一個集合爲輸入,返回單個值的函數。

  • 常用的聚集函數:
    • 平均值 avg
    • 最小值 min
    • 最大值 max
    • 總和 sum
    • 計數 count
  • 分組聚集 group by
  • having子句:對分組限定條件。

包含having和group by 子句的查詢的執行順序:

  1. 先根據from子句計算出一個關係
  2. 如果出現where子句,where子句中的謂詞將應用到from子句的結果關係上
  3. 如果出現group by,則對上面的結果形成分組
  4. 如果出現having,則執行哈慈那個語句
  5. 執行select子句

對空值null進行聚集的原則:除了count(*)外,所有的聚集函數都會忽略輸入集合中的空值

3.8 嵌套子查詢

SQL提供嵌套子查詢機制。子查詢是嵌套在另一個查詢中的select-from-where表達式。

3.8.1 集合成員資格:in, not in

in: 測試元組是否是集合中的成員

not in: 測試元組是否不是集合中的成員

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)

3.8.2 集合的比較

  • some:
    • < some, <=some, >=some, = some, <>some

注意:= some 等價於 in, <>some不等價於not in

select name from instructor where salary > some (select salary from instructor where dept_name = 'Biology');

  • all:
    • < all, <=all, >=all, = all , <>all

注意:<>all 等價於not in, =al不等價於in

select name from instructor where salary > all (select salary from instructor where dept_name = 'Biology');

3.8.3 空關係測試:exists, not exists

exists: 測試一個子查詢的結果中是否存在元素

not exists: 測試一個子查詢的結果中是否不存在元素

3.8.4 重複元組存在性測試unique

unique:用於測試一個子查詢的結果中是否含有重複元組。

not unique: 用於測試在一個子查詢結果中是否存在重複元組

-- 找出所有在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) 
-- 找出所有在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)

3.8.5 from子句中的子查詢

注意:有的數據庫可以支持對嵌套子查詢的進行屬性重命名。但是oracle不支持。

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;

from子句中的嵌套子查詢不能使用凱子from子句中其他關係的相關變量,但是SQL 2003允許from子句中的子查詢使用關鍵詞lateral最爲前綴,以便訪問from子句中在它前面的表或子查詢中的屬性。
 

-- 打印每位教師的姓名,工資以及他們所在的系的平均工資 
select name, salary, avg_salary from instructor I1, lateral (select avg(salary) as avg_salary from instructor I2 where I2.dept_name = I1.dept_name);

3.8.6 with子句

with子句提供定義臨時關係的方法,這個定義只對包含with子句的查詢有效。

-- 找出具有最大預算值的系 
with max_budget(value) as (select max (budget) from department) select budget from department, max_budget where department.budget = max_budget.value;

3.8.7 標量子查詢scalar subquery

若子查詢返回單個屬性的單個元組,則該子查詢稱爲標量子查詢。標量子查詢可以出現select-from-where子句以及having子句中。

-- 列出所有的系,即它們所擁有的教師數 
select dept_name, (select count(*) from instructor where department.dept_name = instructor.dept_name) as num_instructors from department;

3.9 數據庫的修改

  • 刪除
delete from r where P;
  • 插入
insert into r values (v1, v2, ..., vn); 
-- 在執行insert前,先執行完select語句 
insert into r (select (A1, A2, ..., An) from r where P);
  • 更新
update r set A1 = v1 where P; 
-- case結構 
case when pred1 then res1 when pred2 then res2 ... when predn then resn else res0 end 
/* 更新每個student的tot_cred屬性值設爲該生成功 學完的課程的總學分。grade既不是F也不是null,則表明成功學完了該門課程*/
update student S set tot_cred = ( select sum(credits) from takes natural join course where S.ID = takes.ID and takes.grade<>'F' and takes.grode is not null ); 
/*如果學生沒有成功完成任何一門課程,則tot_cred被設置爲null。 如果希望將這樣的屬性值設爲0,那麼需要使用另一條update */
-- ===>上述sql可改寫爲 
update student S set tot_cred = ( select case when sum(credits) is not null then sum(credits) else 0 end from takes natural join course
where S.ID = takes.ID and takes.grade<>'F' and takes.grode is not null);

總結:

  • SQL語言包括幾部分:
    • 數據定義語言DDL:提供了定義關係模式、刪除關係以及修改關係模式的命令
    • 數據操作語言DML:包括查詢語言、以及向數據庫中插入、刪除、修改元組的命令
  • SQL的數據定義語言用於創建具有特定模式的關係。除了聲明關係屬性的名稱和類型之外,SQL還允許聲明完整性約束,例如主碼約束和外碼約束
  • SQL提供了多種用於數據查詢的語言結構:select-from-where子句。SQL支持自然連接操作。
  • SQL提供了對屬性和關係的重命名,以及對查詢結果按照特定屬性排序的機制
  • SQL支持關係上的基本集合運算,包括:並、交、和差運算
  • SQL通過true,false和unknown來處理包含空值的關係的查詢
  • SQL支持聚集函數、可以把關係進行分組,每個分組上單獨運用聚集函數。SQL還支持分組上的集合運算。
  • SQL支持在外層查詢的where和from子句中嵌套子查詢。它還在一個表達式返回的單個值所允許出現的地方支持標量子查詢。
  • SQL提供了更新、插入、刪除信息的結構。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章