<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          SQL太難?你離完全理解SQL就差這10步(上)

          共 4246字,需瀏覽 9分鐘

           ·

          2021-01-19 09:37

          點(diǎn)擊關(guān)注上方“SQL數(shù)據(jù)庫(kù)開發(fā)”,

          設(shè)為“置頂或星標(biāo)”,第一時(shí)間送達(dá)干貨

          很多程序員視 SQL 為洪水猛獸。SQL 是一種為數(shù)不多的聲明性語(yǔ)言,它的運(yùn)行方式完全不同于我們所熟知的命令行語(yǔ)言、面向?qū)ο蟮某绦蛘Z(yǔ)言、甚至是函數(shù)語(yǔ)言(盡管有些人認(rèn)為 SQL 語(yǔ)言也是一種函數(shù)式語(yǔ)言)。

          我們每天都在寫 SQL 并且應(yīng)用在開源軟件 jOOQ 中。于是我想把 SQL 之美介紹給那些仍然對(duì)它頭疼不已的朋友,所以本文是為了以下讀者而特地編寫的:

          • 在工作中會(huì)用到 SQL 但是對(duì)它并不完全了解的人。
          • 能夠熟練使用 SQL 但是并不了解其語(yǔ)法邏輯的人。
          • 想要教別人 SQL 的人。

          本文著重介紹 SELECT 句式,其他的 DML (Data Manipulation Language 數(shù)據(jù)操縱語(yǔ)言命令)將會(huì)在別的文章中進(jìn)行介紹。

          1、 SQL 是一種聲明式語(yǔ)言

          首先要把這個(gè)概念記在腦中:“聲明”。SQL 語(yǔ)言是為計(jì)算機(jī)聲明了一個(gè)你想從原始數(shù)據(jù)中獲得什么樣的結(jié)果的一個(gè)范例,而不是告訴計(jì)算機(jī)如何能夠得到結(jié)果。這是不是很棒?
          (譯者注:簡(jiǎn)單地說,SQL 語(yǔ)言聲明的是結(jié)果集的屬性,計(jì)算機(jī)會(huì)根據(jù) SQL 所聲明的內(nèi)容來從數(shù)據(jù)庫(kù)中挑選出符合聲明的數(shù)據(jù),而不是像傳統(tǒng)編程思維去指示計(jì)算機(jī)如何操作。)

          SELECT?first_name,?last_name?FROM?employees?WHERE?salary?>?100000

          上面的例子很容易理解,我們不關(guān)心這些雇員記錄從哪里來,我們所需要的只是那些高薪者的數(shù)據(jù)(譯者注:salary>100000 )。

          我們從哪兒學(xué)習(xí)到這些?

          如果 SQL 語(yǔ)言這么簡(jiǎn)單,那么是什么讓人們“聞 SQL 色變”?主要的原因是:我們潛意識(shí)中的是按照命令式編程的思維方式思考問題的。就好像這樣:“電腦,先執(zhí)行這一步,再執(zhí)行那一步,但是在那之前先檢查一下是否滿足條件 A 和條件 B ”。例如,用變量傳參、使用循環(huán)語(yǔ)句、迭代、調(diào)用函數(shù)等等,都是這種命令式編程的思維慣式。

          2、 SQL 的語(yǔ)法并不按照語(yǔ)法順序執(zhí)行

          SQL 語(yǔ)句有一個(gè)讓大部分人都感到困惑的特性,就是:SQL 語(yǔ)句的執(zhí)行順序跟其語(yǔ)句的語(yǔ)法順序并不一致。SQL 語(yǔ)句的語(yǔ)法順序是:

          • SELECT[DISTINCT]
          • FROM
          • WHERE
          • GROUP BY
          • HAVING
          • UNION
          • ORDER BY

          為了方便理解,上面并沒有把所有的 SQL 語(yǔ)法結(jié)構(gòu)都列出來,但是已經(jīng)足以說明 SQL 語(yǔ)句的語(yǔ)法順序和其執(zhí)行順序完全不一樣,就以上述語(yǔ)句為例,其執(zhí)行順序?yàn)椋?/p>

          • FROM
          • WHERE
          • GROUP BY
          • HAVING
          • SELECT
          • DISTINCT
          • UNION
          • ORDER BY

          關(guān)于 SQL 語(yǔ)句的執(zhí)行順序,有三個(gè)值得我們注意的地方:

          1、 FROM 才是 SQL 語(yǔ)句執(zhí)行的第一步,并非 SELECT 。數(shù)據(jù)庫(kù)在執(zhí)行 SQL 語(yǔ)句的第一步是將數(shù)據(jù)從硬盤加載到數(shù)據(jù)緩沖區(qū)中,以便對(duì)這些數(shù)據(jù)進(jìn)行操作。(譯者注:原文為“The first thing that happens is loading data from the disk into memory, in order to operate on such data.”,但是并非如此,以 Oracle 等常用數(shù)據(jù)庫(kù)為例,數(shù)據(jù)是從硬盤中抽取到數(shù)據(jù)緩沖區(qū)中進(jìn)行操作。)

          2、 SELECT 是在大部分語(yǔ)句執(zhí)行了之后才執(zhí)行的,嚴(yán)格的說是在 FROM 和 GROUP BY 之后執(zhí)行的。理解這一點(diǎn)是非常重要的,這就是你不能在 WHERE 中使用在 SELECT 中設(shè)定別名的字段作為判斷條件的原因。

          SELECT?A.x?+?A.y?AS?zFROM?AWHERE?z?=?10?-- z 在此處不可用,因?yàn)镾ELECT是最后執(zhí)行的語(yǔ)句!

          如果你想重用別名z,你有兩個(gè)選擇。要么就重新寫一遍 z 所代表的表達(dá)式:

          SELECT?A.x?+?A.y?AS?zFROM?AWHERE?(A.x?+?A.y)?=?10

          …或者求助于衍生表、通用數(shù)據(jù)表達(dá)式或者視圖,以避免別名重用。請(qǐng)看下文中的例子。

          3、 無論在語(yǔ)法上還是在執(zhí)行順序上, UNION 總是排在在 ORDER BY 之前。很多人認(rèn)為每個(gè) UNION 段都能使用 ORDER BY 排序,但是根據(jù) SQL 語(yǔ)言標(biāo)準(zhǔn)和各個(gè)數(shù)據(jù)庫(kù) SQL 的執(zhí)行差異來看,這并不是真的。盡管某些數(shù)據(jù)庫(kù)允許 SQL 語(yǔ)句對(duì)子查詢(subqueries)或者派生表(derived tables)進(jìn)行排序,但是這并不說明這個(gè)排序在 UNION 操作過后仍保持排序后的順序。

          注意:并非所有的數(shù)據(jù)庫(kù)對(duì) SQL 語(yǔ)句使用相同的解析方式。如 MySQL、PostgreSQL和 SQLite 中就不會(huì)按照上面第二點(diǎn)中所說的方式執(zhí)行。

          我們學(xué)到了什么?

          既然并不是所有的數(shù)據(jù)庫(kù)都按照上述方式執(zhí)行 SQL 預(yù)計(jì),那我們的收獲是什么?我們的收獲是永遠(yuǎn)要記得:SQL 語(yǔ)句的語(yǔ)法順序和其執(zhí)行順序并不一致,這樣我們就能避免一般性的錯(cuò)誤。如果你能記住 SQL 語(yǔ)句語(yǔ)法順序和執(zhí)行順序的差異,你就能很容易的理解一些很常見的 SQL 問題。

          當(dāng)然,如果一種語(yǔ)言被設(shè)計(jì)成語(yǔ)法順序直接反應(yīng)其語(yǔ)句的執(zhí)行順序,那么這種語(yǔ)言對(duì)程序員是十分友好的,這種編程語(yǔ)言層面的設(shè)計(jì)理念已經(jīng)被微軟應(yīng)用到了 LINQ 語(yǔ)言中。

          3、 SQL 語(yǔ)言的核心是對(duì)表的引用(table references)

          由于 SQL 語(yǔ)句語(yǔ)法順序和執(zhí)行順序的不同,很多同學(xué)會(huì)認(rèn)為SELECT 中的字段信息是 SQL 語(yǔ)句的核心。其實(shí)真正的核心在于對(duì)表的引用。
          根據(jù) SQL 標(biāo)準(zhǔn),F(xiàn)ROM 語(yǔ)句被定義為:

          ?::=?FROM??[?{???}...?]

          FROM 語(yǔ)句的“輸出”是一張聯(lián)合表,來自于所有引用的表在某一維度上的聯(lián)合。我們們慢慢來分析:

          FROM?a,?b

          上面這句 FROM 語(yǔ)句的輸出是一張聯(lián)合表,聯(lián)合了表 a 和表 b 。如果 a 表有三個(gè)字段, b 表有 5 個(gè)字段,那么這個(gè)“輸出表”就有 8 ( =5+3)個(gè)字段。

          這個(gè)聯(lián)合表里的數(shù)據(jù)是 a*b,即 a 和 b 的笛卡爾積。換句話說,也就是 a 表中的每一條數(shù)據(jù)都要跟 b 表中的每一條數(shù)據(jù)配對(duì)。如果 a 表有3 條數(shù)據(jù), b 表有 5 條數(shù)據(jù),那么聯(lián)合表就會(huì)有 15 ( =5*3)條數(shù)據(jù)。
          FROM 輸出的結(jié)果被 WHERE 語(yǔ)句篩選后要經(jīng)過 GROUP BY 語(yǔ)句處理,從而形成新的輸出結(jié)果。我們后面還會(huì)再討論這方面問題。

          如果我們從集合論(關(guān)系代數(shù))的角度來看,一張數(shù)據(jù)庫(kù)的表就是一組數(shù)據(jù)元的關(guān)系,而每個(gè) SQL 語(yǔ)句會(huì)改變一種或數(shù)種關(guān)系,從而產(chǎn)生出新的數(shù)據(jù)元的關(guān)系(即產(chǎn)生新的表)。

          我們學(xué)到了什么?

          思考問題的時(shí)候從表的角度來思考問題提,這樣很容易理解數(shù)據(jù)如何在 SQL 語(yǔ)句的“流水線”上進(jìn)行了什么樣的變動(dòng)。

          4、 靈活引用表能使 SQL 語(yǔ)句變得更強(qiáng)大

          靈活引用表能使 SQL 語(yǔ)句變得更強(qiáng)大。一個(gè)簡(jiǎn)單的例子就是 JOIN 的使用。嚴(yán)格的說 JOIN 語(yǔ)句并非是 SELECT 中的一部分,而是一種特殊的表引用語(yǔ)句。SQL 語(yǔ)言標(biāo)準(zhǔn)中表的連接定義如下:

          ?::=
          ????
          ??|?
          ??|?

          就拿之前的例子來說:

          FROM?a,?b

          a 可能輸入下表的連接:

          a1?JOIN?a2?ON?a1.id?=?a2.id

          將它放到之前的例子中就變成了:

          FROM?a1?JOIN?a2?ON?a1.id?=?a2.id,?b

          盡管將一個(gè)連接表用逗號(hào)跟另一張表聯(lián)合在一起并不是常用作法,但是你的確可以這么做。結(jié)果就是,最終輸出的表就有了 a1+a2+b 個(gè)字段了。

          (譯者注:原文這里用詞為 degree ,譯為維度。如果把一張表視圖化,我們可以想象每一張表都是由橫縱兩個(gè)維度組成的,橫向維度即我們所說的字段或者列,英文為columns;縱向維度即代表了每條數(shù)據(jù),英文為 record ,根據(jù)上下文,作者這里所指的應(yīng)該是字段數(shù)。)

          在 SQL 語(yǔ)句中派生表的引用甚至比表連接更加強(qiáng)大,下面我們就要講到表連接。

          我們學(xué)到了什么?
          思考問題時(shí),要從表引用的角度出發(fā),這樣就很容易理解數(shù)據(jù)是怎樣被 SQL 語(yǔ)句處理的,并且能夠幫助你理解那些復(fù)雜的表引用是做什么的。
          更重要的是,要理解 JOIN 是構(gòu)建連接表的關(guān)鍵詞,并不是 SELECT 語(yǔ)句的一部分。有一些數(shù)據(jù)庫(kù)允許在 INSERT 、 UPDATE 、 DELETE 中使用 JOIN 。

          5、 SQL 語(yǔ)句中推薦使用表連接

          我們先看看剛剛這句:

          FROM?a,?b

          高級(jí) SQL 程序員也許學(xué)會(huì)給你忠告:盡量不要使用逗號(hào)來代替 JOIN 進(jìn)行表的連接,這樣會(huì)提高你的 SQL 語(yǔ)句的可讀性,并且可以避免一些錯(cuò)誤。
          利用逗號(hào)來簡(jiǎn)化 SQL 語(yǔ)句有時(shí)候會(huì)造成思維上的混亂,想一下下面的語(yǔ)句:

          FROM?a,?b,?c,?d,?e,?f,?g,?h
          WHERE?a.a1?=?b.bx
          AND?a.a2?=?c.c1
          AND?d.d1?=?b.bc
          --?etc...

          我們不難看出使用 JOIN 語(yǔ)句的好處在于:

          • 安全。JOIN 和要連接的表離得非常近,這樣就能避免錯(cuò)誤。

          • 更多連接的方式,JOIN 語(yǔ)句能去區(qū)分出來外連接和內(nèi)連接等。

          我們學(xué)到了什么?

          記著要盡量使用 JOIN 進(jìn)行表的連接,永遠(yuǎn)不要在 FROM 后面使用逗號(hào)連接表。


          本文下篇明天發(fā)~


          來源:水果泡騰片

          鏈接:http://blog.jobbole.com/55086/


          我是岳哥,最后給大家分享我寫的SQL兩件套:《SQL基礎(chǔ)知識(shí)第二版》《SQL高級(jí)知識(shí)第二版》的PDF電子版。里面有各個(gè)語(yǔ)法的解釋、大量的實(shí)例講解和批注等等,非常通俗易懂,方便大家跟著一起來實(shí)操。


          有需要的讀者可以下載學(xué)習(xí),在下面的公眾號(hào)「數(shù)據(jù)前線」(非本號(hào))后臺(tái)回復(fù)關(guān)鍵字:SQL,就行

          數(shù)據(jù)前線
          ——End——

          后臺(tái)回復(fù)關(guān)鍵字:1024,獲取一份精心整理的技術(shù)干貨

          后臺(tái)回復(fù)關(guān)鍵字:進(jìn)群,帶你進(jìn)入高手如云的交流群。

          推薦閱讀

          瀏覽 30
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  五十路熟女影视在线看 | 亚洲无码性爱video | 国产综合久久久7777777 | 操逼福利视频 | 欧美V亚洲 |