如果 SQL 語(yǔ)言這么簡(jiǎn)單,那么是什么讓人們“聞 SQL 色變”?主要的原因是:我們潛意識(shí)中的是按照命令式編程的思維方式思考問題的。就好像這樣:“電腦,先執(zhí)行這一步,再執(zhí)行那一步,但是在那之前先檢查一下是否滿足條件 A 和條件 B ”。例如,用變量傳參、使用循環(huán)語(yǔ)句、迭代、調(diào)用函數(shù)等等,都是這種命令式編程的思維慣式。
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ǔ)句!
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 操作過后仍保持排序后的順序。
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ì)再討論這方面問題。
(譯者注:原文這里用詞為 degree ,譯為維度。如果把一張表視圖化,我們可以想象每一張表都是由橫縱兩個(gè)維度組成的,橫向維度即我們所說的字段或者列,英文為columns;縱向維度即代表了每條數(shù)據(jù),英文為 record ,根據(jù)上下文,作者這里所指的應(yīng)該是字段數(shù)。)