1. 程式人生 > >【SQL】- 基礎知識梳理(六) - 遊標

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

test 觸發器 刪除 管理系統 一支 spa eal har str

遊標的概念

結果集,結果集就是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參數

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

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