天天看點

sql執行順序

sql 不同于與其他程式設計語言的最明顯特征是處理代碼的順序。在大數程式設計語言中,代碼按編碼順序被處理,但是在sql語言中,第一個被處理的子句是from子句,盡管select語句第一個出現,但是幾乎總是最後被處理。

      每個步驟都會産生一個虛拟表,該虛拟表被用作下一個步驟的輸入。這些虛拟表對調用者(用戶端應用程式或者外部查詢)不可用。隻是最後一步生成的表才會傳回 給調用者。如果沒有在查詢中指定某一子句,将跳過相應的步驟。下面是對應用于sql server 2000和sql server 2005的各個邏輯步驟的簡單描述。

(8)select (9)distinct  (11)<top num> <select list>

(1)from [left_table]

(3)<join_type> join <right_table>

(2)on <join_condition>

(4)where <where_condition>

(5)group by <group_by_list>

(6)with <cube | rollup>

(7)having <having_condition>

(10)order by <order_by_list>

邏輯查詢處理階段簡介

from:對from子句中的前兩個表執行笛卡爾積(cartesian product)(交叉聯接),生成虛拟表vt1

on:對vt1應用on篩選器。隻有那些使<join_condition>為真的行才被插入vt2。

outer(join):如 果指定了outer join(相對于cross join 或(inner join),保留表(preserved table:左外部聯接把左表标記為保留表,右外部聯接把右表标記為保留表,完全外部聯接把兩個表都标記為保留表)中未找到比對的行将作為外部行添加到 vt2,生成vt3.如果from子句包含兩個以上的表,則對上一個聯接生成的結果表和下一個表重複執行步驟1到步驟3,直到處理完所有的表為止。

where:對vt3應用where篩選器。隻有使<where_condition>為true的行才被插入vt4.

group by:按group by子句中的列清單對vt4中的行分組,生成vt5.

cube|rollup:把超組(suppergroups)插入vt5,生成vt6.

having:對vt6應用having篩選器。隻有使<having_condition>為true的組才會被插入vt7.

select:處理select清單,産生vt8.

distinct:将重複的行從vt8中移除,産生vt9.

order by:将vt9中的行按order by 子句中的列清單排序,生成遊标(vc10).

top:從vc10的開始處選擇指定數量或比例的行,生成表vt11,并傳回調用者。

注:步驟10,按order by子句中的列清單排序上步傳回的行,傳回遊标vc10.這一步是第一步也是唯一一步可以使用select清單中的列别名的步驟。這一步不同于其它步驟的 是,它不傳回有效的表,而是傳回一個遊标。sql是基于集合理論的。集合不會預先對它的行排序,它隻是成員的邏輯集合,成員的順序無關緊要。對表進行排序 的查詢可以傳回一個對象,包含按特定實體順序組織的行。ansi把這種對象稱為遊标。了解這一步是正确了解sql的基礎。

因為這一步不傳回表(而是傳回遊标),使用了order by子句的查詢不能用作表表達式。表表達式包括:視圖、内聯表值函數、子查詢、派生表和共用表達式。它的結果必須傳回給期望得到實體記錄的用戶端應用程式。例如,下面的派生表查詢無效,并産生一個錯誤:

下面的視圖也會産生錯誤

      在sql中,表表達式中不允許使用帶有order by子句的查詢,而在t—sql中卻有一個例外(應用top選項)。

      是以要記住,不要為表中的行假設任何特定的順序。換句話說,除非你确定要有序行,否則不要指定order by 子句。排序是需要成本的,sql server需要執行有序索引掃描或使用排序運作符。

繼續閱讀