想飛就別怕摔

          大爺的并TM罵人

          SQL小教程【轉】

          一、SQL語言簡介
          SQL是結構化查詢語言(Structured Query Language)的縮寫。這種語言允許我們對數據庫進行復雜的查詢。同時也提供了創建數據庫的方法。SQL語言的使用范圍非常廣泛。許多數據庫產品都支持SQL語言,這意味著如果我們學會了SQL語言,我們可以把這種知識運用到MS Access 或SQL Server, Oracle, DB2以及非常多的其它數據庫中。
           
          SQL語言運用在關系型數據庫中。一個關系型數據庫把數據存儲在表(也稱關系)中。每個數據庫的主要組成就是一組表。每個表又由一組記錄組成--每條記錄在表中有相同的結構,包含固定數量的具有一定類型的字段。
           
          下面我們來看一個實際的數據庫中的表。該表的表名為cia,包含250多條記錄,每個記錄代表一個國家。表由5個字段組成,字段的值有的是字符串類型,有的是數字類型。

          name region area population gdp
          ---- ------ ------ ---------- -----------
          Yemen Middle East 527970 14728474 23400000000
          Zaire Africa 2345410 44060636 18800000000
          Zambia Africa 752610 9445723 7900000000
          Zimbabwe Africa 390580 11139961 17400000000

          下面我們可以用一些SQL語句來查詢這個表中我們該興趣的數據。

          1. 中國的GDP是多少?

          查詢用的SQL語句為:
          select gdp from cia
          where name='china'

          查詢結果為:
          4800000000000

          2. 給出每個地區的國家數和人口總數。并且按地區的人口數從多到少排序。


          查詢用的SQL語句為:

          SELECT region, COUNT(name), SUM(population)
          FROM cia
          GROUP BY region
          ORDER BY 3 DESC

          查詢結果為:
          region COUNT(name) SUM(population)
          ------ ----------- ---------------
          Asia 14 2963031109
          Africa 59 793382933
          Europe 43 580590872
          ....

          怎么樣,對SQL語言有了基本的了解了吧,同時對數據庫,表,記錄,字段等一系列在SQL語言中常用的
          感念也有大概的認識吧。如果不是很清楚也沒關系,在接下來的內容中我們從SQL語言中最簡單
          的內容逐步給大家作介紹,并提供豐富的練習讓大家實際操作。

          二、最基本的SELECT 命令
          select命令或語句用來獲取一個或多個表中的記錄信息,一般配合where子句使用,來取得滿足某些條件的記錄,如果沒有where子句,將返回所有記錄。一般的使用方式如下:

          SELECT attribute-list
          FROM table-name
          WHERE condition

          attribute-list:返回內容的列表,每個內容用逗號分開。這里的內容可以為字段,包含字段的表達式或更復雜的子查詢。

          table-name:表名,更復雜時可以為子查詢。

          condition:條件表達式,用來篩選滿足該條件的記錄。

          在本節中我們使用下表作為試驗之用:

          bbc(name, region, area, population, gdp)
          表名為bbc,該表有5個字段(columns),又稱為屬性(attributes) .
          name :國家名
          region: 國家所在的地區
          area: 面積
          population :人口
          gdp:國民生產總值

          SQL實例:
          1、選出所有國家名,地區和人口
          SELECT name, region, population FROM bbc


          2、給出France的人口數
          SELECT population FROM bbc
          WHERE name = 'France'

          3、哪些國家的名稱以字符D開始?
          SELECT name FROM bbc
          WHERE name LIKE 'D%'

          4、 國土大國(面積大于五百萬平方公里)的國名和人口密度
          SELECT name, population/area FROM bbc
          WHERE area > 5000000

          5、給出一些小(面積小于2000平方公里)而富有(國民生產總值大于50億)的國家
          SELECT name , region
          FROM bbc
          WHERE area < 2000
          AND gdp > 5000000000

          三、SELECT命令中的GROUP BY 和 HAVING 子句
          在介紹GROUP BY 和 HAVING 子句前,我們必需先講講sql語言中一種特殊的函數:聚合函數,例如SUM, COUNT, MAX, AVG等。這些函數和其它函數的根本區別就是它們一般作用在多條記錄上。

          SELECT SUM(population) FROM bbc

          這里的SUM作用在所有返回記錄的population字段上,結果就是該查詢只返回一個結果,即所有國家的總人口數。


          通過使用GROUP BY 子句,可以讓SUM 和 COUNT 這些函數對屬于一組的數據起作用。
          當你指定 GROUP BY region 時, 屬于同一個region(地區)的一組數據將只能返回一行值.
          也就是說,表中所有除region(地區)外的字段,只能通過 SUM, COUNT等聚合函數運算后返回一個值.

          HAVING子句可以讓我們篩選成組后的各組數據.
          WHERE子句在聚合前先篩選記錄.也就是說作用在GROUP BY 子句和HAVING子句前.
          而 HAVING子句在聚合后對組記錄進行篩選。

          讓我們還是通過具體的實例來理解GROUP BY 和 HAVING 子句,還采用第三節介紹的bbc表。

          SQL實例:

          1、顯示每個地區的總人口數和總面積.
          SELECT region, SUM(population), SUM(area)
          FROM bbc
          GROUP BY region

          先以region把返回記錄分成多個組,這就是GROUP BY的字面含義。分完組后,然后用聚合函數對每組中的不同字段(一或多條記錄)作運算。

          2、 顯示每個地區的總人口數和總面積.僅顯示那些面積超過1000000的地區。

          SELECT region, SUM(population), SUM(area)
          FROM bbc
          GROUP BY region
          HAVING SUM(area)>1000000

          在這里,我們不能用where來篩選超過1000000的地區,因為表中不存在這樣一條記錄。
          相反,HAVING子句可以讓我們篩選成組后的各組數據.

          四、嵌套SELECT語句
          嵌套SELECT語句也叫子查詢,形如:

          SELECT name FROM bbc WHERE region =
          (SELECT region FROM bbc WHERE name = 'Brazil')

          一個 SELECT 語句的查詢結果可以作為另一個語句的輸入值。
          上面的SQL語句作用為獲得和'Brazil'(巴西)同屬一個地區的所有國家。

          子查詢不但可以出現在Where子句中,也可以出現在from子句中,作為一個臨時表使用,也可以出現在select list中,作為一個字段值來返回。本節我們僅介紹的Where子句中的子查詢。

          在Where子句中使用子查詢,有一個在實際使用中容易犯的錯在這里說明一下。

          通常,就像上面的例子一樣,嵌套的語句總是和一個值進行比較。語句 (SELECT region FROM bbc WHERE name = 'Brazil') 應該僅返回一個地區,即 'Americas'. 但如果我們在表中再插入一條地區為歐洲,國家名稱為Brazil的記錄,那會發生什么情況?

          這將會導致語句的運行時錯誤.因為這個SQL語句的語法是正確的,所以數據庫引擎就開始執行,但當執行到外部的語句時就出錯了。因為這時的外部語句就像好像是 SELECT name FROM bbc WHERE region = ('Americas', 'Europe'),這個語句當然報錯了。

          那么有沒有辦法解決這個問題呢,當然有。有一些SQL查詢條件允許對列表值(即多個值)進行操作。
          例如"IN" 操作符,可以測試某個值是否在一個列表中。

          下面的語句就可以安全的執行而不出錯,不管表中有多少條包含Brazils的記錄

          SELECT name FROM bbc WHERE region IN
          (SELECT region FROM bbc WHERE name = 'Brazil')

          OK,

          讓我們再看看一些具體的實例,

          1、給出人口多于Russia(俄國)的國家名稱
          SELECT name FROM bbc
          WHERE population>
          (SELECT population FROM bbc
          WHERE name='Russia')

          2、給出'India'(印度), 'Iran'(伊朗)所在地區的所有國家的所有信息
          SELECT * FROM bbc
          WHERE region IN
          (SELECT region FROM bbc
          WHERE name IN ('India','Iran'))

          3、給出人均GDP超過'United Kingdom'(英國)的歐洲國家.

          SELECT name FROM bbc
          WHERE region='Europe' AND gdp/population >
          (SELECT gdp/population FROM bbc
          WHERE name='United Kingdom')

          為了從兩個或多個表中選出數據,我們一般使用表連接來實現這個功能。

          五、SELECT語句中的表連接(join)
          從這里介紹join(連接)的概念. 為此我們準備了兩個試驗用表: album(專輯表) 和 track(曲目表).

          專輯表:包含200首來自Amazon的音樂CD的概要信息。
          album(asin, title, artist, price, release, label, rank)

          曲目表:每張專輯中的曲目(因為是音樂CD,所以也可叫歌曲)的詳細信息。
          track(album, dsk, posn, song)

          SQL短語 FROM album JOIN track ON album.asin=track.album 表示連接album和track表。其中,album.asin表示專輯的惟一標識號,track.album表示曲目表中和專輯關聯的專輯號。
          連接后,得到一個臨時表,該臨時表中每條記錄包含的字段由兩部分組成,除了專輯表中的對應字段album(title, artist ...),還包含曲目表的所有字段track(album, disk, posn and song)。

          有了這張臨時表,很多查詢就容易實現了。

          看看一些具體的實例,

          1、列出歌名為'Alison'的專輯名稱和作者

          SELECT title, artist
          FROM album JOIN track
          ON (album.asin=track.album)
          WHERE song = 'Alison'

          顯然,歌名、專輯名稱和作者分別在兩個表中,必需使用表連接來完成這個查詢。


          2、哪個artist錄制了歌曲'Exodus'

          SELECT artist
          FROM album JOIN track ON (asin=album)
          WHERE song = 'Exodus'

          用作連接的兩個字段asin,album因為在兩個表中都是惟一的,所以不一定要加表名作為前綴。
          但為了方便理解,建議使用前綴,形如:album.asin=track.album

          3、列出曲目表中所有屬于'Blur'專輯的歌曲

          SELECT song
          FROM album JOIN track ON (asin=album)
          WHERE title = 'Blur'

          如果我們把 album JOIN track ON (asin=album) 看成一個臨時表的話,join的概念就很好理解了。

          上節我們介紹了表連接,更確切的說是inner joins內連接.
          內連接僅選出兩張表中互相匹配的記錄.因此,這會導致有時我們需要的記錄沒有包含進來。
          為更好的理解這個概念,我們介紹兩個表作演示。蘇格蘭議會中的政黨表(party)和議員表(msp)。

          party(Code,Name,Leader)
          Code: 政黨代碼
          Name: 政黨名稱
          Leader: 政黨領袖

          msp(Name,Party,Constituency)
          Name: 議員名
          Party: 議員所在政黨代碼
          Constituency: 選區

          六、SELECT語句中的左連接、右連接和全連接
          在介紹左連接、右連接和全連接前,有一個數據庫中重要的概念要介紹一下,即空值(NULL)。

          有時表中,更確切的說是某些字段值,可能會出現空值, 這是因為這個數據不知道是什么值或根本就不存在。
          空值不等同于字符串中的空格,也不是數字類型的0。因此,判斷某個字段值是否為空值時不能使用=,<>這些
          判斷符。必需有專用的短語:IS NULL 來選出有空值字段的記錄,同理,可用 IS NOT NULL 選出不包含空值的記錄。

          例如:下面的語句選出了沒有領導者的政黨。(不要奇怪,蘇格蘭議會中確實存在這樣的政黨)

          SELECT code, name FROM party
          WHERE leader IS NULL

          又如:一個議員被開除出黨,看看他是誰。(即該議員的政黨為空值)

          SELECT name FROM msp
          WHERE party IS NULL

          好了,讓我們言歸正傳,看看什么叫左連接、右連接和全連接。

          A left join(左連接)包含所有的左邊表中的記錄甚至是右邊表中沒有和它匹配的記錄。
          同理,也存在著相同道理的 right join(右連接),即包含所有的右邊表中的記錄甚至是左邊表中沒有和它匹配的記錄。而full join(全連接)顧名思義,左右表中所有記錄都會選出來。

          講到這里,有人可能要問,到底什么叫:包含所有的左邊表中的記錄甚至是右邊表中沒有和它匹配的記錄。
          Ok,我們來看一個實例:

          SELECT msp.name, party.name FROM msp JOIN party ON party=code

          這個是我們上一節所學的Join(注意:也叫inner join),這個語句的本意是列出所有議員的名字和他所屬政黨。
          你可以在 http://sqlzoo.cn/4.htm 親自執行一下該語句,看看結果是什么。

          很遺憾,我們發現該查詢的結果少了兩個議員:Canavan MSP, Dennis。為什么,因為這兩個議員不屬于任和政黨,即他們的政黨字段(Party)為空值。那么為什么不屬于任何政黨就查不出來了?這是因為空值在作怪。因為議員表中政黨字段(Party)的空值在政黨表中找不到對應的記錄作匹配,即FROM msp JOIN party ON party=code 沒有把該記錄連接起來,而是過濾出去了。在該短語中,msp在Join的左邊,所有稱為左表。party在Join的右邊,所有稱為右表。

          Ok,現在再看看這句話,“包含所有的左邊表中的記錄甚至是右邊表中沒有和它匹配的記錄”,意思應該很明白了吧。執行下面這個語句,那兩個沒有政黨的議員就漏不了了。

          SELECT msp.name, party.name FROM msp LEFT JOIN party ON party=code

          關于右連接,看看這個查詢就明白了:

          SELECT msp.name, party.name FROM msp RIGHT JOIN party ON msp.party=party.code

          這個查詢的結果列出所有的議員和政黨,包含沒有議員的政黨,但不包含沒有政黨的議員。

          那么既要包含沒有議員的政黨,又要包含沒有政黨的議員該怎么辦呢,對了,全連接(full join)。

          SELECT msp.name, party.name FROM msp FULL JOIN party ON msp.party=party.code

          七、SELECT語句中的自連接
          到目前為止,我們連接的都是兩張不同的表,那么能不能對一張表進行自我連接呢?答案是肯定的。有沒有必要對一張表進行自我連接呢?答案也是肯定的。

          表的別名:
          一張表可以自我連接。進行自連接時我們需要一個機制來區分一個表的兩個實例。
          在FROM clause(子句)中我們可以給這個表取不同的別名, 然后在語句的其它需要使用到該別名的地方
          用dot(點)來連接該別名和字段名。

          我們在這里同樣給出兩個表來對自連接進行解釋。
          愛丁堡公交線路,

          車站表:
          stops(id, name)

          公交線路表:
          route(num, company, pos, stop)

          1、對公交線路表route進行自連接。

          SELECT * FROM route R1, route R2
          WHERE R1.num=R2.num AND R1.company=R2.company

          我們route表用字段(num, company)來進行自連接. 結果是什么意思呢?你可以知道每條公交線路的任意兩個可聯通的車站。

          2、用stop字段來對route(公交線路表)進行自連接。

          SELECT * FROM route R1, route R2
          WHERE R1.stop=R2.stop;

          查詢的結果就是共用同一車站的所有公交線。這個結果對換乘是不是很有意義呢。

          從這兩個例子我們可以看出,自連接的語法結構很簡單,但語意結果往往不是那么容易理解。就我們這里所列出的兩個表,如果運用得當,能解決很多實際問題,
          例如,任意兩個站點之間如何換乘。

          SELECT R1.company, R1.num
          FROM route R1, route R2, stops S1, stops S2
          WHERE R1.num=R2.num AND R1.company=R2.company
          AND R1.stop=S1.id AND R2.stop=S2.id
          AND S1.name='Craiglockhart'
          AND S2.name='Tollcross'

          posted on 2008-11-12 11:22 生命的綻放 閱讀(342) 評論(0)  編輯  收藏 所屬分類: 數據庫

          <2008年11月>
          2627282930311
          2345678
          9101112131415
          16171819202122
          23242526272829
          30123456

          導航

          統計

          常用鏈接

          留言簿(5)

          隨筆分類(94)

          隨筆檔案(93)

          文章分類(5)

          文章檔案(5)

          相冊

          JAVA之橋

          SQL之音

          兄弟之窗

          常用工具下載

          積分與排名

          最新評論

          閱讀排行榜

          主站蜘蛛池模板: 通辽市| 富川| 黄冈市| 高邑县| 饶阳县| 大连市| 盐亭县| 彰武县| 三明市| 汝南县| 百色市| 平武县| 巩留县| 古浪县| 卢龙县| 克拉玛依市| 濮阳县| 博爱县| 无锡市| 天津市| 金昌市| 灵宝市| 抚松县| 通海县| 浮梁县| 中西区| 康定县| 丽水市| 达尔| 夏津县| 拉孜县| 郯城县| 和龙市| 竹山县| 潼关县| 天祝| 阳原县| 潍坊市| 大新县| 丁青县| 米脂县|