【SQL】- 基礎知識梳理(六) - 游標


游標的概念

結果集,結果集就是select查詢之后返回的所有行數據的集合。

游標(Cursor):

  • 是處理數據的一種方法。
  • 它可以定位到結果集中的某一行,對數據進行讀寫。
  • 也可以移動游標定位到你需要的行中進行數據操作。
  • 是面向集合的數據庫管理系統和面向行的程序設計之間的橋梁

游標的分類

SQL Server支持的API服務器游標分為4種:
靜態游標( STATIC )意味着,當游標被建立時,將會創建FOR后面的SELECT語句所包含數據集的副本存入tempdb數據庫中,任何對於底層表內數據的更改不會影響到游標的內容。
動態游標( DYNAMIC )是和STATIC完全相反的選項,當底層數據庫更改時,游標的內容也隨之得到反映,在下一次fetch中,數據內容會隨之改變。
鍵集驅動游標( KEYSET )可以理解為介於STATIC和DYNAMIC的折中方案。將游標所在結果集的唯一能確定每一行的主鍵存入tempdb,當結果集中任何行改變或者刪除時,@@FETCH_STATUS會為-2,KEYSET無法探測新加入的數據。
只進游標    可以理解成不支持滾動,只支持從頭到尾順序提取數據,數據庫執行增刪改,在提取時是可見的,但由於該游標只能進不能向后滾動,所以在行提取后對行做增刪改是不可見的。 ( FAST_FORWARD 可以理解為FORWARD_ONLY的優化版本.FORWARD_ONLY執行的是靜態計划,而FAST_FORWARD是根據情況進行選擇采用動態計划還是靜態計划,大多數情況下FAST_FORWARD要比FORWARD_ONLY性能略好。

游標的語法

DECLARE cursor_name CURSOR [ LOCAL |GLOBAL ] 
     [ FORWARD_ONLY | SCROLL ] 
     [ STATIC | KEYSET | DYNAMIC | FAST_FORWARD ] 
     [ READ_ONLY | SCROLL_LOCKS | OPTIMISTIC ] 
     [ TYPE_WARNING ] 
     FOR select_statement 
     [ FOR UPDATE [ OF column_name [ ,...n ] ] ]

cursor_name:游標名稱。
Local:作用域為局部,只在定義它的批處理,存儲過程或觸發器中有效。
Global:作用域為全局,由連接執行的任何存儲過程或批處理中,都可以引用該游標。
[Local | Global]:默認為local。
Forward_Only:指定游標智能從第一行滾到最后一行。 Fetch Next是唯一支持的提取選項。如果在指定Forward_Only時不指定Static、KeySet、Dynamic關鍵字,默認為Dynamic游標。如果Forward_Only和Scroll沒有指定,Static、KeySet、Dynamic游標默認為Scroll,Fast_Forward默認為Forward_Only
Static:靜態游標
KeySet:鍵集游標
Dynamic:動態游標,不支持Absolute提取選項
Fast_Forward:指定啟用了性能優化的Forward_Only、Read_Only游標。
Read_Only:意味着聲明的游標只能讀取數據,游標不能做任何更新操作
Scroll_Locks:將讀入游標的所有數據進行鎖定,防止其他程序進行更改,以確保更新的絕對成功
Optimistic:是相對比較好的一個選擇,OPTIMISTIC不鎖定任何數據,當需要在游標中更新數據時,如果底層表數據更新,則游標內數據更新不成功,如果,底層表數據未更新,則游標內表數據可以更新。
Type_Warning:指定將游標從所請求的類型隱式轉換為另一種類型時向客戶端發送警告信息。
For Update[of column_name ,....] :定義游標中可更新的列。

如何定義游標

游標變量支持兩種方式賦值,定義時賦值和先定義后賦值,定義游標變量像定義其他局部變量一樣,在游標前加”@”,注意,如果定義全局的游標,只支持定義時直接賦值,並且不能在游標名稱前面加“@”,兩種定義方式如下:
--定義后直接賦值
DECLARE test_Cursor CURSOR FOR
SELECT * FROM TABLE1
--先定義后賦值
DECLARE @test_Cursor2 CURSOR
SET @test_Cursor2=CURSOR FOR
SELECT * FROM TABLE2

--定義后直接賦值
DECLARE test_Cursor CURSOR LOCAL FOR
SELECT * FROM TABLE1
DECLARE test_Cursor2 CURSOR GLOBAL FOR
SELECT * FROM TABLE2
--用GO結束上面作用域
GO
--打開游標
OPEN test_Cursor
OPEN test_Cursor2
全局游標在批處理結束后依然有效
局部游標在批處理結束后被隱式釋放,無法再其他批處理中引用
  如果不指定游標作用域,默認作用域為GLOBAL
 注意,當全局游標和局部游標變量重名時,默認會打開局部變量游標

提取游標語法 

Fetch
[ [Next|prior|Frist|Last|Absoute n|Relative n ]
from
[Global] cursor_name
into @variable_name[,....]]
參數說明:
Frist:結果集的第一行
Prior:當前位置的上一行
Next:當前位置的下一行
Last:最后一行
Absoute n:從游標的第一行開始數,第n行。
Relative n:從相對當前位置數,第n行。(n為負數向前數,否則向后)
Into @variable_name[,...] : 將提取到的數據存放到變量variable_name中。
注意:    對於未指定SCROLL選項的游標來說,只支持NEXT取值.

實戰創建游標

准備表數據

創建游標

--聲明游標
declare test_Cursortable3 CURSOR FOR
SELECT id,NAME FROM TABLE3
--打開游標
OPEN test_Cursortable3
--聲明游標提取變量所要存放的變量
declare @id int,@name varchar(20)
--定位游標到哪一行
fetch next from test_Cursortable3 into @id,@name    --into的變量數量必須需與游標查詢結果的列數相同
--fetch FIRST from test_Cursortable3 into @id,@name
while @@FETCH_STATUS=0  --提取成功,進行下一條數據的提取操作
begin
    if @id=2
    begin
    Update TABLE3 Set sex='0' Where Current of test_Cursortable3 --更新當前行
    end
    if  @id=10
    begin
    delete TABLE3 where current  of test_Cursortable3    --刪除當前行
    end
fetch next from test_Cursortable3 into @id,@name    --移動游標
end
--關閉游標
close    test_Cursortable3
--釋放游標
deallocate test_Cursortable3

執行結果

注釋:

@@fetch_status是MicroSoft SQL SERVER的一個全局變量
其值有以下三種,分別表示三種不同含義[返回類型integer]
0 FETCH 語句成功
-1 FETCH 語句失敗或此行不在結果集中
-2 被提取的行不存在

 

使用游標時注意事項:

游標打開后,服務器會專門為游標分配一定的內存空間存放游標操作的數據結果集,同時使用游標也會對某些數據進行封鎖。所以游標一旦用過,應及時關閉,避免服務器資源浪費。

盡量不要在大量數據上定義游標
盡量不要使用游標上更新數據
盡量不要使用insensitive, static和keyset這些參數定義游標
如果可以,盡量使用FAST_FORWARD關鍵字定義游標
如果只對數據進行讀取,當讀取時只用到FETCH NEXT選項,則最好使用FORWARD_ONLY參數

如果能不用游標,盡量不要使用游標


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM