不帶ORDER BY 子句的查詢返回的是一個集合(或多集),而帶有ORDER BY 子句的查詢返回的是一種ANSI 稱爲遊標(cursor)的對象,由於這種結果的行之間具備固定的順序,因此不是關係的結果。函數
在默認狀況下應該使用基於集合的查詢,只在有使人信服的理由時才考慮使用遊標。對象
由於基礎
1.若是使用遊標,就嚴重違背了關係模型,關係模型要求按照集合來考慮問題。變量
2.遊標逐行對記錄進行操做會帶來必定的開銷。和基於集合的操做相比,遊標分別對每一記錄進行操做,這確定會帶來必定的額外開銷。給定一個基於集合的查詢,以及一段在幕後用遊標完成相似物理處理的代碼,遊標代碼一般比基於集合的代碼要慢許多倍。循環
3.使用遊標,須要爲解決方案的物理操做編寫不少代碼,換句話說,得寫不少代碼來描述如何處理數據(聲明遊標、打開遊標、循環遍歷遊標記錄、關閉遊標、釋放遊標)。而使用基於集合的解決方案,則主要關注於問題的邏輯方面,也就是說,只要描述要獲取什麼,而沒必要描述如何獲取它們。所以,與基於集合的解決方案相比,基於遊標的解決方案一般代碼更長,可讀性更低,也更加難以維護。遍歷
使用遊標一般涉及如下步驟:數據
1. 在某個查詢的基礎上聲明遊標。查詢
2. 打開遊標。db
3. 從第 1 個遊標記錄中把列值提取到指定的變量。集合
4. 當尚未超出遊標的最後一行時(@@FETCH_STATUS 函數的返回值是0),循環遍歷遊標記錄;在每一次遍歷中,從當前遊標記錄中把列值提取到指定的變量,再爲當前行執行相應的處理。
5. 關閉遊標。
6. 釋放遊標。
DECLARE @ID intDECLARE @Name nvarchar(max)DECLARE C CURSOR FOR SELECT categoryId,categoryname FROM dbo.Categories -- 定義遊標OPEN C -- 打開遊標FETCH NEXT FROM C INTO @ID,@Name -- 移向第一個遊標--SELECT @ID+@NameWHILE @@FETCH_STATUS=0BEGIN SELECT str(@ID)+@Name FETCH NEXT FROM C INTO @ID,@Name --移向下一條數據ENDCLOSE C; -- 關閉遊標DEALLOCATE C -- 釋放遊標