SQL 語句的執行順序 問題
SELECT
從數據庫中檢索行,并允許從一個或多個表中選擇一個或多個行或列。雖然 SELECT 語句的完整語法較復雜,但是其主要的子句可歸納如下:
SELECT select_list
[ INTO new_table ]
FROM table_source
[ WHERE search_condition ]
[ GROUP BY group_by_expression ]
[ HAVING search_condition ]
[ ORDER BY order_expression [ ASC | DESC ] ]
可以在查詢之間使用 UNION 運算符,以將查詢的結果組合成單個結果集。
語法
SELECT statement ::=
< query_expression >
[ ORDER BY { order_by_expression | column_position [ ASC | DESC ] }
[ ,。n ] ]
[ COMPUTE
{ { AVG | COUNT | MAX | MIN | SUM } ( expression ) } [ ,。n ]
[ BY expression [ ,。n ] ]
]
[ FOR { BROWSE | XML { RAW | AUTO | EXPLICIT }
[ , XMLDATA ]
[ , ELEMENTS ]
[ , BINARY base64 ]
}
]
[ OPTION ( < query_hint > [ ,。n ]) ]
< query expression > ::=
{ < query specification > | ( < query expression > ) }
[ UNION [ ALL ] < query specification | ( < query expression > ) [。n ] ]
< query specification > ::=
SELECT [ ALL | DISTINCT ]
[ { TOP integer | TOP integer PERCENT } [ WITH TIES ] ]
< select_list >
[ INTO new_table ]
[ FROM { < table_source > } [ ,。n ] ]
[ WHERE < search_condition > ]
[ GROUP BY [ ALL ] group_by_expression [ ,。n ]
[ WITH { CUBE | ROLLUP } ]
]
[HAVING <search_condition>]
詳細的請看一下sql的幫助文件。
SQL語句是按什么順序執行的
分析器會先看語句的第一個詞,當它發現第一個詞是SELECT關鍵字的時候,它會跳到FROM關鍵字,然后通過FROM關鍵字找到表名并把表裝入內存。
接著是找WHERE關鍵字,如果找不到則返回到SELECT找字段解析,如果找到WHERE,則分析其中的條件,完成后再回到SELECT分析字段。 最后形成一張我們要的虛表。
其它的先不說了,只說WHERE。 WHERE關鍵字后面的是條件表達式。
如果學過C語言等編程語言就會知道,條件表達式計算完成后,會有一個返回值,即非0或0,非0即為真(true),0即為假(false)。同理WHERE后面的條件也有一個返回值,真或假,來確定接下來執不執行SELECT。
例: SELECT * FROM STUDENT WHERE SNO = '1'; 分析器先找到關鍵字SELECT,然后跳到FROM關鍵字將STUDENT表導入內存,并通過指針p1找到第一條記錄,接著找到WHERE關鍵字計算它的條件表達式,如果為真那么把這條記錄裝到一個虛表當中,p1再指向下一條記錄。 如果為假那么p1直接指向下一條記錄,而不進行其它操作。
一直檢索完整個表,關把虛表返回給用戶。 再說EXISTS謂詞,EXISTS謂詞也是條件表達式的一部分。
當然它也有一個返回值(true或false)。 例: SELECT Sname FROM Student WHERE EXISTS (SELECT * FROM SC WHERE SC。
Sno = Student。Sno AND SC。
Cno = '1'); 這是一個SQL語句的嵌套使用,但和上面說的SQL語句的執行過程也是相同的。嵌套的意思也就是說當分析主SQL語句(外面的那個SELECT,我們權且先這么叫它)到WHERE關鍵字的時候,又進入了另一個SQL語句中。
那么也就是說,分析器先找到表Student并裝入內存,一個指針(例如p1)指向Student表中的第一條記錄。然后進入WHERE里分析里面的SQL語句,再把SC表裝入內存,另一個指針(例如p2)指向SC表中的第一條記錄,分析WHERE后面的條件表達式,依次進行分析,最后分析出一個虛表2,也就變成 SELECT Sname FROM Student WHERE EXISTS 虛表2 如果虛表為空表,EXISTS 虛表2 也就為false,不返回到SELECT,而p1指向下一條記錄。
如果虛表2不為空也就是有記錄,那么EXISTS 虛表2 為true同,返回到SELECT并把p1指向的記錄添加到主SQL語句的虛表1當中。
為什么SQL語句要按標準順序寫
好像自已在書寫 SQL 語句時由于不清楚各個關鍵字的執行順序, 往往組織的 SQL 語句缺少很好的邏輯, 憑感覺 "拼湊" ( 不好意思, 如果您的 SQL 語句也經常 "拼湊", 那您是不是得好好反省一下呢?). 確實是爽了自己, 可苦了機器, 服務器還需要在我們的雜亂無章的 SQL 語句中尋找它下一句需要執行的關鍵字在哪里. 效率嘛, 由于我們的感覺神經對秒以下的變化實在不敏感, 暫且就認為自已寫的 SQL 順序無關緊要, "反正沒什么變化!", 呵呵.其實服務器對每句 SQL 解析時間都會有詳細記錄的, 大家可以看一下自已按習慣寫的 SQL 和按標準順序寫的SQL解析時間差別有多大. 因此,建議大家在平時工作中 SQL 語句按標準順序寫, 一是專業, 二是實用, 呵呵, 不過覺得最主要的是心里感覺舒服.。
用SQL語句實現兩個語句的順序執行
有兩種方法:
方法一: 使用linked_server_*_name,例如:
select * from ERP..*
linked_server_name Linked server referencing the OLE DB data source
catalog Catalog in the OLE DB data source that contains the object
schema Schema in the catalog that contains the object
object_name Data object in the schema
SQL Server用linked_server_name取linked server相關配置信息,然后將catalog、schema、object_name作為參數傳遞給OLEDB。例如遠程鏈接服務器為SQL Server時catalog為數據庫實例名,schema為owner id (dbo);鏈接服務器為Oracle時 (OLEDB),catalog為空,schema為用戶
注意點:
a). 遠程鏈接服務器為Oracle時schema、object_name必須大寫(其他類型的不清楚),否則會報錯
消息 7314,級別 16,狀態 1,第 1 行
鏈接服務器 "ERP" 的 OLE DB 訪問接口 "MSDAORA" 不包含表 ""CRM"."INQ""。該表不存在,或者當前用戶沒有訪問該表的權限。
b). 必須使用完整的名稱。例如SQL Server本地執行sql,dbo可以省略不寫,使用遠程鏈接服務器時則必須提供
方法二:使用openquery,例如:
select *
from openquery(ERP,'select t.* from(select inq.*,rownum as rindex from inq order by img01) t where *>=51 and *<=100')
優點:
a). SQL Server只是將openquery中的sql發送給遠程服務器執行,因此可以使用遠程鏈接服務器的所有sql語法(例如Oracle語法),sql對象也不必大寫
b). 數據類型的異常很少(個別情況下還是會發生)
c). openquery的寫法同樣可用于update、insert、delete
d). 鏈接服務器為Oracle時,schema不必出現在sql語句中
關于使用鏈接服務器方面的一些限制、前提條件,可以參考https://**en-us/library/aa172718(SQL.80).aspx
https://**en-us/library/aa213288(SQL.80).aspx
請教一條sql語句的執行順序
這個我正好有收藏O(∩_∩)O哈哈~
1、FROM:對FROM子句中的前兩個表執行笛卡爾積(Cartesian product)(交叉聯接),生成虛擬表VT1
2、ON:對VT1應用ON篩選器。只有那些使<join_condition>;為真的行才被插入VT2。
3、outer(JOIN):如 果指定了OUTER JOIN(相對于CROSS JOIN 或(INNER JOIN),
保留表(preserved table:左外部聯接把左表標記為保留表,右外部聯接把右表標記為保留表,
完全外部聯接把兩個表都標記為保留表)
中未找到匹配的行將作為外部行添加到 VT2,生成VT3.如果FROM子句包含兩個以上的表,
則對上一個聯接生成的結果表和下一個表重復執行步驟1到步驟3,直到處理完所有的表為止。
4、WHERE:對VT3應用WHERE篩選器。只有使<where_condition>;為true的行才被插入VT4.
5、 group by:按GROUP BY子句中的列列表對VT4中的行分組,生成VT5.
6、CUBE|ROLLUP:把超組(Suppergroups)插入VT5,生成VT6.
7、HAVING:對VT6應用HAVING篩選器。只有使<having_condition>;為true的組才會被插入VT7.
8、SELECT:處理SELECT列表,產生VT8.
9、DISTINCT:將重復的行從VT8中移除,產生VT9.
10、order by:將VT9中的行按ORDER BY 子句中的列列表排序,生成游標(VC10).
TOP:從VC1