亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 開發 > 綜合 > 正文

簡單十步讓你全面理解SQL

2024-07-21 02:50:40
字體:
來源:轉載
供稿:網友
簡單十步讓你全面理解SQL

 很多程序員認為SQL是一頭難以馴服的野獸。它是為數不多的聲明性語言之一,也因為這樣,其展示了完全不同于其他的表現形式、命令式語言、面向對象語言甚至函數式編程語言(雖然有些人覺得SQL還是有些類似功能)。

  我每天都寫SQL,我的開源軟件JOOQ中也包含SQL。因此我覺得有必要為還在為此苦苦掙扎的你呈現SQL的優美!下面的教程面向于:

  • 已經使用過但沒有完全理解SQL的讀者

  • 已經差不多了解SQL但從未真正考慮過它的語法的讀者

  • 想要指導他人學習SQL的讀者

  本教程將重點介紹SELECT語句。其他DML語句將在另一個教程中在做介紹。接下來就是…

  1、SQL是聲明性語言

  首先你需要思考的是,聲明性。你唯一需要做的只是聲明你想獲得結果的性質,而不需要考慮你的計算機怎么算出這些結果的。

SELECT first_name, last_name FROM employees WHERE salary > 100000

  這很容易理解,你無須關心員工的身份記錄從哪來,你只需要知道誰有著不錯的薪水。

  從中我們學到了什么呢?

  那么如果它是這樣的簡單,會出現什么問題嗎?問題就是我們大多數人會直觀地認為這是命令式編程。如:“機器,做這,再做那,但在這之前,如果這和那都發生錯誤,那么會運行一個檢測”。這包括在變量中存儲臨時的編寫循環、迭代、調用函數,等等結果。

  把那些都忘了吧,想想怎么去聲明,而不是怎么告訴機器去計算。

  2、SQL語法不是“有序的”

  常見的混亂源于一個簡單的事實,SQL語法元素并不會按照它們的執行方式排序。語法順序如下:

  • SELECT [DISTINCT]

  • FROM

  • WHERE

  • GROUP BY

  • HAVING

  • UNION

  • ORDER BY

  為簡單起見,并沒有列出所有SQL語句。這個語法順序與邏輯順序基本上不同,執行順序如下:

  • FROM

  • WHERE

  • GROUP BY

  • HAVING

  • SELECT

  • DISTINCT

  • UNION

  • ORDER BY

  這有三點需要注意:

  1、第一句是FROM,而不是SELECT。首先是將數據從磁盤加載到內存中,以便對這些數據進行操作。

  2、SELECT是在其他大多數語句后執行,最重要的是,在FROM和GROUPBY之后。重要的是要理解當你覺得你可以從WHERE語句中引用你定義在SELECT語句當中的時候,。以下是不可行的:

SELECT A.x + A.y AS zFROM AWHERE z = 10 -- z is not available here!

  如果你想重用z,您有兩種選擇。要么重復表達式:

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

  或者你使用派生表、公用表表達式或視圖來避免代碼重復。請參閱示例進一步的分析:

  3、在語法和邏輯順序里,UNION都是放在ORDER BY之前,很多人認為每個UNION子查詢都可以進行排序,但根據SQL標準和大多數的SQL方言,并不是真的可行。雖然一些方言允許子查詢或派生表排序,但卻不能保證這種順序能在UNION操作后保留。

  需要注意的是,并不是所有的數據庫都以相同的形式實現,例如規則2并不完全適用于MySQL,PostgreSQL,和SQLite上

  從中我們學到了什么呢?

  要時刻記住SQL語句的語法順序和邏輯順序來避免常見的錯誤。如果你能明白這其中的區別,就能明確知道為什么有些可以執行有些則不能。

  如果能設計一種在語法順序上實際又體現了邏輯順序的語言就更好了,因為它是在微軟的LINQ上實現的。

  3、SQL是關于數據表引用的

  因為語法順序和邏輯順序的差異,大多數初學者可能會誤認為SQL中列的值是第一重要的。其實并非如此,最重要的是數據表引用。

  該SQL標準定義了FROM語句,如下:

<from clause> ::= FROM &lt;table reference&gt; [ { &lt;comma&gt; &lt;table reference&gt; }... ]

  ROM語句的"output"是所有表引用的結合程度組合表引用。讓我們慢慢地消化這些。

FROM a, b

  上述產生一個a+b度的組合表引用,如果a有3列和b有5列,那么"輸出表"將有8(3+5)列。

  包含在這個組合表引用的記錄是交叉乘積/笛卡兒積的axb。換句話說,每一條a記錄都會與每一條b記錄相對應。如果a有3個記錄和b有5條記錄,然后上面的組合表引用將產生15條記錄(3×5)。

  在WHERE語句篩選后,GROUP BY語句中"output"是"fed"/"piped",它已轉成新的"output",我們會稍后再去處理。

  如果我們從關系代數/集合論的角度來看待這些東西,一個SQL表是一個關系或一組元素組合。每個SQL語句將改變一個或幾個關系,來產生新的關系。

  從中我們學到了什么呢?

  一直從數據表引用角度去思考,有助于理解數據怎樣通過你的sql語句流水作業的

  4、SQL數據表引用可以相當強大

  表引用是相當強大的東西。舉個簡單的例子,JOIN關鍵字其實不是SELECT語句的一部分,但卻是"special"表引用的一部分。連接表,在SQL標準中有定義(簡化的):

<table reference> ::=<table name>| <derived table>| <joined table>

  如果我們又拿之前的例子來分析:

FROM a, b

  a可以作為一個連接表,如:

a1 JOIN a2 ON a1.id = a2.id

  這擴展到前一個表達式,我們會得到:

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

  雖然結合了數據表引用語法與連接表語法的逗號分隔表讓人很無語,但你肯定還會這樣做的。結果,結合數據表引用將有a1+a2+b度。

  派生表甚至比連接表更強大,我們接下來將會說到。

  從中我們學到了什么呢?

  要時時刻刻考慮表引用,重要的是這不僅讓你理解數據怎樣通過你的sql語句流水作業的,它還將幫助你了解復雜表引用是如何構造的。

  而且,重要的是,了解JOIN是構造連接表的關鍵字。不是的SELECT語句的一部分。某些數據庫允許JOIN在插入、更新、刪除中使用。

  5、應使用SQL JOIN的表,而不是以逗號分隔表

  前面,我們已經看到這語句:

FROM a, b

  高級SQL開發人員可能會告訴你,最好不要使用逗號分隔的列表,并且一直完整的表達你的JOINs。這將有助于改進你的SQL語句的可讀性從而防止錯誤出現。

  一個非常常見的錯誤是忘記某處連接謂詞。思考以下內容:

FROM a, b, c, d, e, f, g, hWHERE a.a1 = b.bxAND a.a2 = c.c1AND d.d1 = b.bc-- etc...

  使用join來查詢表的語法

  • 更安全,你可以把連接謂詞與連接表放一起,從而防止錯誤。

  • 更富于表現力,你可以區分外部連接,內部連接,等等。??

  從中我們學到了什么呢?

  使用JOIN,并且永遠不在FROM語句中使用逗號分隔表引用。

  6、SQL的不同類型的連接操作

  連接操作基本上有五種

  • EQUI JOIN

  • SEMI JOIN

  • ANTI JOIN

  • CROSS JOIN

  • DIVISION

  這些術語通常用于關系代數。對上述概念,如果他們存在,SQL會使用不同的術語。讓我們仔細看看:

  EQUI JOIN(同等連接)

  這是最常見的JOIN操作。它有兩個子操作:

  • INNER JOIN(或者只是JOIN)

  • OUTER JOIN(可以再次拆分為LEFT, RIGHT,FULL OUTER JOIN)

  例子是其中的區別最好的解釋:

-- This table reference contains authors and their books.-- There is one record for each book and its author.-- authors without books are NOT includedauthor JOIN book ON author.id = book.author_id-- This table reference contains authors and their books-- There is one record for each book and its author.-- ... OR there is an "empty" record for authors without books-- ("empty" meaning that all book columns are NULL)author LEFT OUTER JOIN book ON author.id = book.author_id

  SEMIJOIN(半連接)

  這種關系的概念在SQL中用兩種方式表達:使用IN謂詞或使用EXISTS謂語。"Semi"是指在拉丁語中的"half"。這種類型的連接用于連接只有"half"的表引用。再次考慮上述加入的作者和書。讓我們想象,我們想要作者/書的組合,但只是那些作者實際上也有書。然后我們可以這樣寫:

-- Using INFROM authorWHERE author.id IN (SELECT book.author_id FROM book)-- Using EXISTSFROM authorWHERE EXISTS (SELECT 1 FROM book WHERE book.author_id = author.id)

  雖然不能肯定你到底是更加喜歡IN還是EXISTS,而且也沒有規則說明,但可以這樣說:

  • IN往往比EXISTS更具可讀性

  • EXISTS往往比IN更富表現力(如它更容易表達復雜的半連接)

  • 一般情況下性能上沒有太大的差異,但,在某些數據庫可能會有巨大的性能差異。

  因為INNER JOIN有可能只產生有書的作者,因為很多初學者可能認為他們可以使用DISTINCT刪除重復項。他們認為他們可以表達一個像這樣的半聯接:

-- Find only those authors who also have booksSELECT DISTINCT first_name, last_nameFROM author

  這是非常不好的做法,原因有二:

  • 它非常慢,因為該數據庫有很多數據加載到內存中,只是要再刪除重復項。

  • 它不完全正確,即使在這個簡單的示例中它產生了正確的結果。但是,一旦你JOIN更多的表引用,,你將很難從你的結果中正確刪除重復項。

  更多的關于DISTINCT濫用的問題,可以訪問這里的博客。

  ANTI JOIN(反連接)

  這個關系的概念跟半連接剛好相反。您可以簡單地通過將NOT關鍵字添加到IN或EXISTS中生成它。在下例中,我們選擇那些沒有任何書籍的作者:

-- Using INFROM authorWHERE author.id NOT IN (SELECT book.author_id FROM book)-- Using EXISTSFROM authorWHERE NOT EXISTS (SELECT 1 FROM book WHERE book.author_id = author.id)

  同樣的規則對性能、可讀性、表現力都適用。然而,當使用NOTIN時對NULLs會有一個小警告,這個問題有點超出本教程范圍。

  CROSSJOIN(交叉連接)

  結合第一個表中的內容和第二個表中的內容,引用兩個join表交叉生成一個新的東西。我們之前已經看到,這可以在FROM語句中通過逗號分隔表引用來實現。在你確實需要的情況下,可以在SQL語句中明確地寫一個CROSS JOIN。

-- Combine every author with every bookauthor CROSS JOIN book

  DIVISION(除法)

  關系分割就是一只真正的由自己親自喂養的野獸。簡而言之,如果JOIN是乘法,那么除法就是JOIN的反義詞。在SQL中,除法關系難以表達清楚。由于這是一個初學者的教程,解釋這個問題超出了我們的教程范圍。當然如果你求知欲爆棚,那么就看這里,這里還有這里。

  從中我們學到了什么呢?

  讓我們把前面講到的內容再次牢記于心。SQL是表引用。連接表是相當復雜的表引用。但關系表述和SQL表述還是有點區別的,并不是所有的關系連接操作都是正規的SQL連接操作。對關系理論有一點實踐與認識,你就可以選擇JOIN正確的關系類型并能將其轉化為正確的SQL。

  7、SQL的派生表就像表的變量

  前文,我們已經了解到SQL是一種聲明性語言,因此不會有變量。(雖然在一些SQL語句中可能會存在)但你可以寫這樣的變量。那些野獸一般的表被稱為派生表。

  派生表只不過是包含在括號里的子查詢。

-- A derived tableFROM (SELECT * FROM author)

  需要注意的是,一些SQL方言要求派生表有一個關聯的名字(也被稱為別名)。

-- A derived table with an aliasFROM (SELECT * FROM author) a

  當你想規避由SQL子句邏輯排序造成的問題時,你會發現派生表可以用帥呆了來形容。例如,如果你想在SELECT和WHERE子句中重用一個列表達式,只寫(Oracle方言):

-- Get authors' first and last names, and their age in daysSELECT first_name, last_name, ageFROM (SELECT first_name, last_name, current_date - date_of_birth ageFROM author)-- If the age is greater than 10000 daysWHERE age > 10000

  注意,一些數據庫和SQL:1999標準里已將派生表帶到下一級別,,引入公共表表達式。這將允許你在單一的SQL SELECT中重復使用相同的派生表。上面的查詢將轉化為類似這樣的:

WITH a AS (SELECT first_name, last_name, current_date - date_of_birth ageFROM author)SELECT *FROM aWHERE age > 10000

  很明顯,對廣泛重用的常見SQL子查詢,你也可以灌輸具體"a"到一個獨立視圖中。想要了解更多就看這里。

  從中我們學到了什么呢?

  再溫習一遍,SQL主要是關于表引用,而不是列。好好利用這些表引用。不要害怕寫派生表或其他復雜的表引用。

  8、SQLGROUPBY轉換之前的表引用

  讓我們重新考慮我們之前的FROM語句:

FROM a, b

  現在,讓我們來應用一個GROUP BY語句到上述組合表引用

GROUP BY A.x, A.y, B.z

  這會產生一個只有其余三個列(!)的新的表引用。讓我們再消化一遍。如果你用了GROUP BY,那么你在所有后續邏輯條款-包括選擇中減少可用列的數量。這就是為什么你只可以從SELECT語句中的GROUP BY語句引用列語法的原因。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
在线视频免费一区二区| 国产香蕉一区二区三区在线视频| 日韩一二三在线视频播| 亚洲国产91色在线| 九色91av视频| 国产视频综合在线| 成人精品久久久| 欧美成人sm免费视频| 国产精品成人av性教育| 2019日本中文字幕| 亚洲精品一区二区三区婷婷月| 欧洲日本亚洲国产区| 国内精品久久久久久久久| 亚洲免费电影在线观看| 日韩在线视频导航| 欧美在线视频免费观看| 一区二区欧美激情| 亚洲欧美日韩精品久久| 亚洲成人激情图| 日韩av片永久免费网站| 欧美丰满少妇xxxx| 亚洲精品成人久久久| 亚洲人成在线免费观看| 亚洲国产日韩一区| 欧洲成人在线视频| 最好看的2019年中文视频| 国产精品爽爽爽爽爽爽在线观看| 久久久这里只有精品视频| 色偷偷噜噜噜亚洲男人| 日韩av免费看网站| 久久久久亚洲精品国产| 欧美久久久精品| 欧美日韩裸体免费视频| 国产日韩欧美另类| 成人午夜激情免费视频| 国产精品九九九| 亚洲区在线播放| 欧美乱人伦中文字幕在线| 日韩福利在线播放| 亚洲国产欧美自拍| 欧美极品少妇xxxxⅹ免费视频| 日本一区二区不卡| 欧美亚洲在线观看| 久久久久久久999| 国产丝袜一区视频在线观看| 日本一区二区在线免费播放| 日韩中文字幕视频在线| 国产亚洲美女久久| 亚洲欧美国产高清va在线播| 亚洲精品久久久久久久久久久久| 91中文字幕在线| 久久香蕉国产线看观看网| 国产成人福利夜色影视| 国产精品网站大全| 久久久免费观看| 国产一区二区三区在线视频| 欧美另类极品videosbestfree| 国产成人精品久久二区二区| 国产97在线观看| 亚洲一区二区三区乱码aⅴ蜜桃女| 在线精品国产成人综合| 久久99青青精品免费观看| 日韩欧中文字幕| 精品久久久久久久久久久久久久| 国产精品高精视频免费| 日日骚av一区| 色中色综合影院手机版在线观看| 色爱av美腿丝袜综合粉嫩av| 岛国av一区二区三区| 国产精品久久久久av免费| 高清视频欧美一级| 亚洲综合在线做性| 久久精品福利视频| 国外成人在线视频| 国产一区二区精品丝袜| 午夜精品一区二区三区视频免费看| 97在线视频免费观看| 久久久精品视频成人| 欧美日韩亚洲国产一区| 国产精品成av人在线视午夜片| 国产欧美精品一区二区三区介绍| 亚洲国产私拍精品国模在线观看| 日韩中文av在线| 国产精品入口夜色视频大尺度| 日韩精品视频在线观看免费| 久久久久中文字幕2018| 久久亚洲电影天堂| 国产成人一区二区三区小说| 亚洲国产精品网站| 青草青草久热精品视频在线网站| 国产精品永久免费观看| 91麻豆国产精品| 久久精品久久久久| 永久免费看mv网站入口亚洲| 狠狠综合久久av一区二区小说| 欧美中文在线字幕| 欧美成人自拍视频| 国产精品色午夜在线观看| 成人高h视频在线| 高清日韩电视剧大全免费播放在线观看| 免费91在线视频| 国模吧一区二区| 欧美日韩亚洲精品一区二区三区| 97精品国产97久久久久久春色| 国产99久久久欧美黑人| 亚洲国产精品久久久久秋霞不卡| 国产午夜精品麻豆| 久久深夜福利免费观看| 中文字幕国产亚洲2019| 68精品久久久久久欧美| 在线中文字幕日韩| 中文字幕日韩有码| 国产精品在线看| 91精品成人久久| 中文字幕精品一区二区精品| 国产精品久久久久久久app| 国产97色在线|日韩| 国产欧美一区二区三区久久| 国产盗摄xxxx视频xxx69| 九九热在线精品视频| 久久综合国产精品台湾中文娱乐网| 国产精品福利在线观看| 神马久久桃色视频| 亚洲精品综合久久中文字幕| 中文字幕在线观看日韩| 久久久精品久久久| 中文字幕亚洲图片| 亚洲精品自拍第一页| 中文字幕精品在线| 亚洲视频第一页| 日韩av中文字幕在线| 98精品国产自产在线观看| 日韩欧美大尺度| 欧美日韩亚洲91| 欧美人交a欧美精品| 欧美日韩成人精品| 青青草国产精品一区二区| 久久久精品999| 一区二区三欧美| 最近2019年日本中文免费字幕| 亚洲天堂网在线观看| 国产v综合v亚洲欧美久久| 成人高清视频观看www| 欧美多人爱爱视频网站| 午夜精品一区二区三区av| 91国产视频在线| 欧美肥婆姓交大片| 中文字幕欧美专区| 欧美在线视频观看免费网站| 97在线精品国自产拍中文| 最近2019年手机中文字幕| 久久久人成影片一区二区三区观看| 精品国产91乱高清在线观看| 91夜夜揉人人捏人人添红杏| 精品视频一区在线视频| 韩国日本不卡在线| 91免费的视频在线播放| 亚洲国产精品资源| 亚洲人成电影在线播放| 久久综合伊人77777尤物| 亚洲国产高清福利视频| 欧美成人精品一区| 久久久久久久久久久人体| 亚洲欧美国产精品|