數據庫系統概念-----SQL

本節目錄

1、SQL查詢語言概覽

2、SQL 數據定義

3、SQL查詢的基本結構

4、附加的基本運算

5、集合運算

6、空值

7、聚集函數

8、嵌套子查詢

9、數據庫修改

10、總結


1、SQL查詢語言概覽

        SQL語言有以下幾個部分:

        *數據定義語言(DDL):SQL DDL提供定義關係模式,刪除關係以及修改關係模式的命令。

        *數據操縱語言(DML):SQL DML提供從數據庫中查詢信息以及在數據庫中插入元組、刪除元組、修改元組的能力。

        *完整性:SQL DDL包括定義完整性約束的命令,保存在數據庫中的數據必須滿足所定義的完整性約束,破壞完整性約束的更新是不被允許的。

        *視圖定義:SQL DDL包括定義視圖的命令。

         *事務控制:SQL包括定義事務的開始和結束的命令。

        *嵌入式SQL和動態SQL:嵌入式和動態SQL定義SQL語句如何嵌入到通用編程語言。

        *授權:SQL DDL包括定義對關係和視圖的訪問權限命令。

2、SQL 數據定義

        數據庫中的關係集合必須由數據定義語言(DDL)指定給系統,SQL的DDL不僅能夠定義一組關係,還能定義每個關係的信息,包括:1)每個關係的模式。2)每個屬性的取值類型。3)完整性約束。4)每個關係維護的索引集合。5)每個關係的安全性和權限信息。6)每個關係在磁盤上的物理存儲。

    2.1 基本類型

        SQL標準支持多種固有類型。包括:

        *char:固定長度的字符串,用戶指定長度n,也可以在使用character

        *varchar:可變長度的字符串,用戶指定最大長度n,等價於全稱character varing。

        *int:整數類型,等價於全稱integer

        *smallint:小整數類型,

        *numeric(p,d):定點數,精度由用戶指定,這個數有p位數字(加一個符號位),其中d位數字在小數點右邊。所以numeric(3,1)這個可以存儲44.5,但不能存儲444.5或者0.32這樣的數。

        *real,double precision:浮點數與雙精度浮點數。

        *float(n):精度至少爲n位的浮點數

        每種類型都有可能包含一個空值的特殊值,空值表示一個缺失的值,該值可能存在但是不爲人所知,或者可能根本不存在,在可能的情況下,我們希望禁止加入空值。

    2.2 基本模式定義

        使用create table命令定義SQL關係,下面的命令在數據庫中創建了一個department關係。

        

        上面創建的關係具有三個屬性,dept_name是最大長度爲20的字符串,building是最大長度爲15的字符串,budget是一個12位的數,其中兩位是小數點後面,create table還指明瞭dept_name屬性是department關係的主碼。

        create table命令的通用形式是:

        

        其中r是關係名,每個Ai 是關係r模式中的一個屬性名,Di是屬性Ai的域,也就是說,D制定了屬性A的類型以及可選的約束,用於限制所允許的A取值的集合。

        create table命令後面用分號結束。其他的SQL語句也是如此,下面是幾個完整性約束:

        *primary key(A1,A2,.....Am):聲明屬性A1,A2..構成關係的主碼。主碼屬性必須非空且唯一,也就是說沒有一個元組在主碼屬性上取空值,關係中也沒有兩個元組在所有主碼屬性上取值相同,雖然主碼的聲明是可選的,但是爲每一個關係指定一個主碼通常會更好。

        *foreign key(A1,A2,....Am) references S:聲明表示關係中任意元組在屬性(A1,A2..Am)上的取值必須對應關係S中某元組在主碼屬性上的取值。比如下圖:course表中聲明瞭foreign key(dept_name) references department。此外碼聲明表明對於每個課程元組來說,該院組所標識的系名必然存在於department關係的主碼屬性(dept_name)。沒有這個約束的話就可能某門課程指定一個不存在的系名。

        

        *not null:一個屬性上的not null約束表明在該屬性上不允許有空值,換句話說,此約束把空值排除在該屬性域之外。如下圖表示,dept_name的值不能爲空。

        

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

        一個新創建的關係最初是空的,可以使用inset命令將數據加載到關係中,例如下圖,值被給出的順序應該遵循對應關係屬性在關係模型中列出的順序。

        

        可以使用delete命令從關係中刪除元組,命令:delete from student;將從student關係中刪除所有元組。

       如果要去掉一個關係使用,drop table命令。drop table命令從數據庫中刪除關於被去掉關係的所有信息,命令drop table r是比delete from r更強的語句,後者保留關係r,但是刪除r中的元組。前者不僅刪除元組,還刪除r的模式。一旦r被去掉,除非使用create table命令重建r,否則不能有元組插入到r中。

        可以使用alter table 命令爲已有的關係增加屬性。其命令格式爲

        

        其中r是現有關係名稱,A是待添加的屬性名稱,D是待添加的屬性的域,同樣可以通過

        

         從關係中去掉屬性,r爲現有關係,A是關係的一個屬性名。

3、SQL查詢的基本結構

        SQL查詢的基本結構由三個字句構成:select、from和where。查詢的輸入是在from字句中列出的關係,在這些關係上進行where和select字句中指定的運算,產生一個關係作爲結果。

    3.1 單關係查詢

        考慮使用大學數據庫例子的一個簡單查詢“找出所有老師的姓名”,教師的姓名可以在instructor關係中找到,因此,把這個關係放到from字句中,教師姓名出現在name屬性中,把它放在select字句中。

        

        現在考慮另一個查詢,找出所有教師所在的系名。可以寫成

        

        在關係模型的形式化數學定義中,關係是一個集合,因此,重複的元組不會出現在關係中,在實踐中去除重複是相當費時的,所以SQL允許在關係以及SQL表達式中出現重複,因此上面的查詢語句結果中,每個出現的系名都會在結果中,如果我們想要強行刪除重複們可以在select後加入關鍵字,distinct。上面的查詢就變成了下圖,這樣每個系名最多出現一次。

        

       SQL允許我們使用關鍵字all來顯式知名不去除重複。

        

        SQL字句還可以帶有加減乘除運算符的算術表達式,運算的對象可以使常數或元組的屬性。如下:

        

        返回一個和instructor一樣的關係,只是屬性salary是原來的1.1倍。

        where字句允許我們只選出那些在from子句的結果關係中滿足特定謂詞的元組。如下語句:

        

        表示的是,從instructor表中找出dept_name爲Comp.Sci並且salary大於70000的教師的姓名。where子句可以使用邏輯連詞and,or和not。邏輯連詞的運算對象可以是包含比較運算符<、<=、>、>=、=和<>的表達式。SQL允許使用比較運算符來比較字符串、算術表達式以及特殊類型。

    3.2 多關係查詢

        如下語句:

        

        表示的是找出所有老師的姓名,以及他們所在系的系名,和系所在的建築名稱。需要注意的是,所需要的信息出於兩個不同的關係,並且關係的每個元組都要與另一個關係的每個元組相對應。還有一個需要注意的是如果一個屬性只出現在一個關係中,那麼不需要用關係名作爲前綴,如果屬性在多個關係中都有,那麼需要使用關係名作爲前綴。

        一個SQL查詢可以包括三種類型的子句,select子句、from子句、where子句。每種字句的作用如下:select子句用於列出查詢結果中所需要的屬性,from子句是一個查詢求值中需要訪問的關係列表,where子句是一個作用在from子句中關係的屬性上的謂詞。

        通過from子句定義一個在該子句中所列出的關係上的笛卡爾積(笛卡爾乘積是指在數學中,兩個集合XY的笛卡尓積(Cartesian product),又稱直積,表示爲X×Y,第一個對象是X的成員而第二個對象是Y的所有可能有序對的其中一個成員)。

        where子句中的謂詞用來限制笛卡爾積所建立的組合,只留下對答案有意義的組合。

        通常來說,一個SQL查詢語句的含義可以理解爲下:1)爲from子句中列出的關係產生笛卡爾積。2)在步驟1的結果上應用where子句中指定的謂詞。3)對步驟2結果中的每個元組輸出select子句中指定的屬性。

        where子句的條件需要小心設置。

    3.3 自然連接

        自然連接運算作用於兩個關係,產生一個關係作爲結果,不同於兩個關係上的笛卡爾積,它將第一個關係的每個院組和第二個關係的所有元組都進行連接;自然連接只會考慮那些在兩個關係模式中都出現的屬性上取值相同的元組對。也就是兩個關係中相同的屬性。

        

        對於之前的一個查詢,找到對於大學中所有講授課程的教師,找出他們的姓名以及講述的所有課程標識。此前我們所寫的查詢語句是這樣的:

        

        但是利用自然連接之後,便可以這樣寫:

        

        兩者產生的結果是一樣的。自然連接的結果是關係。在一個SQL查詢from子句中,可以用自然連接將多個關係結合在一起。如下:

        

        爲了更好地發揮自然連接的優點,避免不必要的相等屬性帶來的危險,SQL提供了一種自然連接的構造形式,允許用戶來指定需要哪些列相等,如下:

        

        join...using運算中需要給定一個屬性名列表,其中兩個輸入中都必須有指定名稱的屬性。運算r1 join r2 using(A1,A2)它和r1和r2的自然連接類似。只不過在t1.A1=t2.A1並且t1.A2=t2.A2成立的前提下,來自r1的元組t1和來自r2的元組t2就能匹配,即使r1和r2都有具有A3的屬性,也不需要t1.A3=t2.A3成立。

4、附加的基本運算

    a

        看一下之前使用過的查詢:

        

        查詢的結果是一個具有下列屬性的關係:name,course_id結果中的屬性名來自from子句中關係的屬性名。SQL提供了一個重命名結果關係中屬性的方法,如下使用as語句。

        

       as子句既可以出現在select子句中,也可以出現在from子句中。比如如果想用instructor_name來代替屬性名name,重寫上面的查詢,

        

        類似如下圖的查詢:

        

        T和S可以看做instructor關係的兩個拷貝,更準確地說是instructor關係的別名。一般被稱作相關名稱,或者表別名,或者相關變量、元組變量。

    4.2 字符串運算

        SQL用一對字符串表示字符串,如果單引號是字符串的一部分,那就用兩個單引號字符來表示。字符串操作函數不同的數據庫系統是不同的。

        在字符串上可以使用like操作符來實現模式匹配,使用兩個特殊的字符來描述模式:

        *百分號(%):匹配任意字串

        *下劃線(_):匹配任意一個字符,大小寫要區分。

        *Intro%:匹配任何以Intro開頭的字符

        *%Comp%匹配任何包含“Comp”子串的字符串

        *(___)匹配只含有三個字符的字符串

        *(___%)匹配至少含有三個字符的字符串

        在SQL中用比較運算符like來表達模式,查詢“找出所在建築名稱中包含子串‘Wastson’"的所有系名。寫法如下:

        

        爲了使模式中能包含特殊模式的字符即(%和_)SQL允許定義轉義字符,轉義字符直接放在特殊字符的前面,表示該特殊字符爲普通字符。在like比較運算中使用escape關鍵字定義轉義字符。

        like 'ab\%cd%' escape '\' 匹配所有以"ab%cd"開頭的所有字符串。

        like 'ab\\cd%' escape '\' 匹配所有以"ab\cd"開頭的字符串。

        SQL允許使用not like比較運算符搜尋不匹配項。

    4.3 select子句中的屬性說明

        星號“*”可以用在select子句中表示所有的屬性。類似正則表達式。

    4.4 排列元組的顯示次序

        SQL爲用戶提供了一些對關係中元組顯示次序的空值。order by子句就可以讓查詢結果中元組按排列順序顯示。比如按照字母順序列出Physics系所有的教師。可以這樣寫:

        

        order by子句默認使用升序,要說明排列順序,可以用desc表示降序,或者用asc表示升序。排序可以在多個屬性上進行。比如希望按照工資的降序,如果工資一樣再按照姓名升序排列。語句如下:

        

    4.5 where子句謂詞

        爲了簡化where子句,SQL提供了between比較運算符來說明一個值是小於或等於某個值,同時大於或等於另一個值,比如找出工資在90000到100000之間的教師的姓名,語句如下:

        

        這樣在where子句中就不用了使用salary>90000 and salary<100000。

        SQL允許使用記號(V1,V2....Vn)表示一個分量值分別爲V1,V2,....Vn的n維元組。在元組上可以使用比較運算符,按照字典順序進行比較運算。例如(a1,a2)<=(b1,b2)在a1<=b1且a2<=b2時爲真,類似的兩個元組在所有屬性上相等時,它們是相等的。

5、集合運算

        SQL作用在關係上的union、intersect和except運算對應於數學集合論中的並交和-運算。以下面的集合爲例:

        

    5.1 並運算

        找出在2009年秋季開課,或者2010年春季開課或兩個學習都開課的所有課程,查詢語句如下:

        

        union運算會自動去除重複,這樣會去除掉在兩個季節都開的課程只保留一個。如果想保留重複,使用union all代替union。

    5.2 交運算

        找出2009秋季和2010春季同時開課的所有課程的集合。如下:

        

        intersect運算也會自動去除重複,如果有一門課程在春季開了4個課程段,在春季開了兩個課程段,那麼結果還是隻有一個課程。和union 一樣,如果想保留重複元素,使用intersect all 代替intersect。

    5.3 差運算

        找出在2009年秋季開課但不在2010年春季開課的所有課程,查詢語句如下:

        

        except運算從第一個輸入中輸出所有不在第二個輸入中的元組,也就是執行集差操作。此運算在執行差操作之前自動去除輸入中的重複,和之前一樣,不想去除重複使用except all 代替except。

6、空值

        空值給關係運算帶來了特殊的問題,包括算術運算、比較運算和集合運算。

        如果算術表達式的任一輸入爲空,則該算術表達式(+、-、*、/)結果爲空。

        SQL涉及空值的比較運算的結果視爲unknown,這是除了true、false之外的第三個邏輯值。由於在where子句的爲此種可以對比較結果使用諸如and、or和not的布爾運算,所以這些布爾運算的定義也被擴展到可以處理unknown值。

        *and:true and unknow 結果是unknow,false and unknow結果是false。unknow and unknow 的結果是unknow。

        *or :true or unknow 結果是true ,false or unknow結果是unknow ,unknow or unknow結果是unknow。

        *not:not unknow結果是unknow。

        如果where子句對一個元祖計算出false或unknow,那麼該元組不能被加到結果集中。

        SQL在謂詞中使用特殊的關鍵詞null測試空值,因而爲找出instructor關係中salary爲空值的所有教師可以寫成如下:

        

        如果is null爲非空,則爲真。某些SQL語句還允許使用子句is unknow和is not unknow來測試一個表達式的結果是否爲unknow。在select distinct子句時,重複元組將被去除。爲了達到這個目的,當比較兩個元組對應的屬性值時,如果這兩個值都是非空並且值相等或者都爲空,那麼它們是相同的。

7、聚集函數

        聚集函數是以值得一個集合爲輸入,返回單個值的函數,SQL提供了五個固有聚集函數,avg(平均值)、min(最小值)、max(最大值)、sum(總和)、count(計數)。

    7.1 基本聚集

        查詢某個系教師的平均工資,查詢語句如下:

        

        數據庫系統可以給結果關係的屬性一個任意的名字,這個屬性是聚集產生的,可以用as子句給屬性一個有意義的名稱。如下:

        

        SQL COUNT(DISTINCT column_name) 語法:COUNT(DISTINCT column_name) 函數返回指定列的不同值的數目:

        使用聚集函數conut計算一個關係元組的個數,SQL中該函數的寫法是count(*),如下:count(*)不能和distinct一起使用。

        

    7.2 分組聚集

        group by可以將聚集函數作用在一組元組集上。group by子句中給出的一個或多個屬性是用來構造分組的。在group by子句中所有屬性取值相同的元組將被分在一個組中。

        查詢每個系的平均工資,查詢語句如下:

        

        上面的語句會先根據dept_name屬性進行分組的情況,分組是計算查詢結果的第一步,然後在每個分組上進行指定的聚集計算。如下圖,是先分組之後的結果。

        

        查詢的結果如下圖:

        

        如果不使用group by 語句那麼整個關係會被當做一個分組。當SQL查詢使用分組時,一個很重要的事情是,需要保證出現在select語句中,但是沒有被聚集的屬性只能是出現在group by子句的屬性。也就是說,任何沒有出現在group by子句的屬性如果出現在select子句中的話,它只能出現聚集函數內部,否則這樣的查詢是錯誤的。

    7.3 having 子句

        有時候,對分組的限定條件比對元組的限定條件更加有用,該條件不針對單個元組,而是針對group by構成的分組,可以使用having 子句,having 子句中的謂詞在形成分組後才起作用,可以使用聚集函數。

        

        上述語句表示的是,系平均工資超過42000的那些教師的平均工資。和select子句情況類似,任何出現在having 子句中沒有被聚集的屬性必須出現在group by子句中,否則查詢就是錯誤的。

    7.4 對空值和布爾值的聚集

        空值的存在給聚集運算的處理帶來了麻煩。總而言之,聚集函數根據以下原則處理空值:除了count(*)外的所有聚集函數都忽略輸入集合中的空值。由於空值被忽略,有可能造成參加函數運算的輸入集合爲空集,規定空集的count運算值爲0,其他所有聚集運算在輸入爲空集的情況下返回一個空值,在一些更復雜的SQL結構中空值的影響更難判定。

        布爾數據類型,可以取true、false、unknow三個值,有兩個聚集函數,some和every,其含義正如直觀意義一樣,可以處理布爾類型值。

8、嵌套子查詢

        SQL 提供嵌套子查詢機制,子查詢是嵌套在另一個查詢中的select-from-where表達式。子查詢嵌套在where子句中,通常用於對集合的成員資格、集合的比較以及集合的基數進行檢查。

    8.1 集合成員資格

        SQL允許測試元組關係中的成員資格,連接詞in測試元組是否是集合中的成員,集合是由select子句產生的一組值構成的。連接詞not in則測試元組是否不是集合中的成員。

        在之前做過一個查詢,09年秋季和10年春季都開設的課程,之前是使用兩個集合的交運算,現在可以使用嵌套查詢的方式。

        

        也可以使用與in結構類似的方式使用not in結構。

    8.2 集合的比較

        SQL提供一種比較,短語至少比某一個大在SQL中用>some表示。如下:

        

        SQL也允許<some,<=some,=some和<>some。類似於some,SQL也允許<all,>all,=all等。

    8.3 空關係測試

        SQL還有一個特性可以測試一個子查詢結果中是否存在元組。exists結構在作爲參數的子查詢非空時返回true值,使用exists結構,我們還能用另外一種方法書寫查詢,如下:

        

        

        上面的查詢說明了,來自外層查詢的一個相關名稱,可以用在where子句的子查詢中,使用了來自外層查詢的相關的子查詢被稱爲相關子查詢。

        可以用 not exists結構測試子查詢結構中集中是否不存在元組。

    8.4 重複元組存在性測試

        SQL提供一個布爾函數,用於測試在一個子查詢的結果中是否存在重複元組。如果作爲參數的子查詢結果中沒有重複的元組,unique結構返回true值。

        

        可以使用not unique結構測試在一個子查詢結果中是否存在重複元組。

    8.5 from子句中的子查詢

        SQL允許在from子句中使用子查詢表達式。之前做過一個查詢,找出系平均工資超過42000的系中教師平均工資,之前是使用having子句來寫的,現在可以這樣:

        

        不是所有SQL實現都支持from子句嵌套。一般from子句嵌套的子查詢不能使用來自from其他關係的變量。但是2003以後,允許from 子句的子查詢使用關鍵字lateral作爲前綴,訪問from子句中前面的表或子查詢中的屬性。

    8.6 with 子句

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

        

        with子句定義了臨時關係max_budget,此關係在隨後的查詢中馬上被使用了。

    8.7 標量子查詢

        SQL允許子查詢出現在返回單個值得表達式能出現在任何地方,只要該子查詢只返回包含單個屬性的單個元組。這樣的子查詢成爲標量子查詢。如下:

        

        列出所有的系以及他們擁有的教師數,上面的子查詢保證返回單個值,因爲它使用了不帶group by的count(*)聚集函數。標量子查詢可以出現在select、where和having子句中,也可以不使用聚集函數來定義標量子查詢,在編譯時,並非總能判斷一個子查詢返回的結果中是否有多個元組,如果子查詢被執行後結果中不只有一個元組,則產生一個運行時錯誤。

9、數據庫修改

    9.1 刪除

        刪除請求的表達與查詢非常類似,我們只能刪除整個元組,而不能刪除某些屬性上的值。SQL用如下語句表示刪除

        

        其中P代表一個謂詞,r表示一個關係。delete語句首先從r中找出所有使P(t)爲真的元組t,然後把它們從r中刪除。如果省略where,則r中所有元組將被刪除。

        delete只能作用於一個關係,如果想從多個關係中刪除元組,必須在每個關係上是用一條delete命令。where子句中的謂詞可以和selete命令的where子句中謂詞一樣複雜,另一種情況下,where子句可以爲空,這樣將會刪除整個關係中的元組,但是關係本身還是存在的。

        delete語句可以使用嵌套。

    9.2 插入

        要往關係中插入數據,我們可以指定帶插入的元組,或者寫一條查詢語句來生成待插入的元組集合,顯然待插入的元組的屬性值必須在相同屬性的域中,待插入的分量數也必須是正確的。

        最簡單的insert語句是單個元組的插入請求,如下:

        

        元組屬性的排列順序和關係模式中屬性排列順序一致,考慮到用戶可能不記得關係屬性的排列順序,SQL允許在insert語句中指定屬性,如下:

        

        更通常的情況是,可能想在查詢結果的基礎上插入元組,如下:

        

        沒有指定元組,而是用select選出一個元組,在執行插入。在插入之前先執行完select語句是非常重要的。如果在執行select語句同時執行插入動作,並且在關係上沒有主碼約束,這樣會插入無數元組。

        待插入元組可以只給出模式中部分屬性的值,其餘屬性將被賦空值,用null表示。

        大部分關係數據庫,有特殊的“bulk loader”工具,可以向一個關係中插入一個非常大的元組集合。這些工具允許從格式化文本中讀出數據,且執行速度比通道能目的的插入語句序列要快得多。

    9.3 更新

        有些情況下,我們可能希望在不改變整個元組的情況下改變其部分屬性的值。爲了達到這一目的,可以使用update數據與使用insert、delect類似,待更新的元組可以用查詢語句找到。

             

        上述語句將instructor關係上的每個元組都執行。

          

        上述是將工資小於70000的教師漲工資。update語句中嵌套select可以引用待更新的關係。SQL提供case結構,可以利用它在一條update語句中執行前面兩種更新,避免更新次序引發的問題:

        

        標量子查詢在SQL更新語句中也很有用,可以用在set子句中。如下語句

        

        上述語句的意思是,將student元組的tot_cred屬性設置爲,該學生成功學完的課程的學分總和,假設一個學生的成績既不是F,也不是空,那麼他成功學完這門課程。上面的語句如果一個學生沒有學完課程,則tot_cred會設置爲空,如果想要將其設置爲0,那麼可以使用將select sum子句替換成使用case表達式。

        

10、總結

        *SQL語言包括:數據定義語言(DDL),它提供定義關係模式,刪除關係和修改關係模式的命令。數據操縱語言(DML)它包括查詢語言、以及往數據庫中插入元組、刪除元組和修改元組

        *SQL的數據定義語言用於創建具有特定模式的關係,除了聲明關係屬性的名稱和類型之外,SQL還允許提供聲明完整性約束,主碼約束和外碼約束。

        *SQL提供多種用於查詢數據庫的語言結構,其中包括select、from和where子句,SQL還支持自然連接。

       *SQL提供對屬性和關係重命名。

       *SQL支持關係上的基本集合運算,包括交併和差運算。

       *SQL通過真值true、false並且增加unknow,來處理對包含空值的關係查詢。

       *SQL支持聚集,可以把關係進行分組,在每個分組上單獨運用聚集。

       *SQL支持在外層查詢的where和from子句中嵌套子查詢。

        

 

        

        

        

        

 

        

        

        

        

 

 

        

        

    

 

 

 

 

 

 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章