MS-SQL游標(biāo)的使用及理解 windows或DOS的“光標(biāo)”不同,MS-SQL的游標(biāo)是一種臨時(shí)的數(shù)據(jù)庫 對(duì)象,既對(duì)可用來旋轉(zhuǎn)儲(chǔ)存在系統(tǒng)永久表中的數(shù)據(jù)行的副本,也可以指向儲(chǔ)存在系統(tǒng)永久表中的數(shù)據(jù)行的指針。
游標(biāo)為您提供了在逐行的基礎(chǔ)上而不是一次處理整個(gè)結(jié)果集為基礎(chǔ)的操作表中數(shù)據(jù)的方法。 1.如何使用游標(biāo) 1)定義游標(biāo)語句 Declare Cursor For 2)創(chuàng)建游標(biāo)語句 Open 3)提取游標(biāo)列值、移動(dòng)記錄指針 Fetch From [Into ] 4)使用@@Fetch_Status利用While循環(huán)處理游標(biāo)中的行 5)刪除游標(biāo)并釋放語句 Close /Deallocate 6)游標(biāo)應(yīng)用實(shí)例 –定義游標(biāo) Declare cur_Depart Cursor For Select cDeptID,cDeptName From Department into @DeptID,@DeptName –創(chuàng)建游標(biāo) Open cur_Depart –移動(dòng)或提取列值 Fetch From cur_Depart into @DeptID,@DeptName –利用循環(huán)處理游標(biāo)中的列值 While @@Fetch_Status=0 Begin Print @DeptID,@DeptName Fetch From cur_Depart into @DeptID,@DeptName End –關(guān)閉/釋放游標(biāo) Close cur_Depart Deallocate cur_Depart 2.語句的詳細(xì)及注意 1)定義游標(biāo)語句 Declare [Insensitive] [Scroll] Cursor For [FOR {Read Only | Update [ OF ]}] Insensitive DBMS創(chuàng)建查詢結(jié)果集數(shù)據(jù)的臨時(shí)副本(而不是使用直接引用數(shù)據(jù)庫表中的真實(shí)數(shù)據(jù)行中的列)。游標(biāo)是Read Only,也就是說不能修改其內(nèi)容或底層表的內(nèi)容; Scroll 指定游標(biāo)支持通過使用任意Fetch 選項(xiàng)(First Last Prior Next Relative Absolute)選取它的任意行作為當(dāng)前行。如果此項(xiàng)省略,則游標(biāo)將只支持向下移動(dòng)單行(即只支持游標(biāo)的Fetch Next); Select語句 定義游標(biāo)結(jié)果集的標(biāo)準(zhǔn) SELECT 語句。在游標(biāo)聲明的 內(nèi)不允許使用關(guān)鍵字 COMPUTE、COMPUTE BY、FOR BROWSE 和 INTO; Read Only 防止使用游標(biāo)的用戶通過更新數(shù)據(jù)或刪除行改變游標(biāo)的內(nèi)容; Update 創(chuàng)建可更新游標(biāo)且列出值能被更新的游標(biāo)列。如果子句中列入了任意列,則只有被列入的列才能被更新。如果Declare Cursor語句中只指定的UPDATE(沒有列名列表),則游標(biāo)將允許更新它的任何或所有列。 Declare cur_Depart Cursor For Select * From Department For Update OF cDeptID,cDeptName 2)提取游標(biāo)列值、移動(dòng)記錄指針語句 Fetch [Next | Prior | First | Last | {Absolute } | {Relative }] From [Into ] 每次執(zhí)行Fetch語句時(shí),DBMS移到游標(biāo)中的下一行并把游標(biāo)中的列值獲取到Into中列出的變量中。因此Fetch語句的Into子句中列出的變量必須與游標(biāo)定義中Select 語句中的列表的類型與個(gè)數(shù)相對(duì)應(yīng); 僅當(dāng)定義游標(biāo)時(shí)使用Scroll參數(shù)時(shí),才能使用Fetch語句的行定位參數(shù)(First Last Prior Next Relative Absolute);如果Fetch語句中不包括參數(shù)Next | Prior | First | Last,DBMS將執(zhí)行默認(rèn)的Fetch Next; Next 向下、向后移動(dòng)一行(記錄); Prior 向上、向前移動(dòng)一行(記錄); First 移動(dòng)至結(jié)果集的第一行(記錄); Last 移動(dòng)至結(jié)果集的最后一行(記錄); Absolute n 移動(dòng)到結(jié)果集中的第n行。如果n是正值,DBMS從結(jié)果集的首部向后或向下移動(dòng)至第n行;如果n是負(fù)數(shù),則DBMS從結(jié)果集的底部向前或向上移動(dòng)n行; Fetch Absolute 2 From cur_Depart Into @DeptID,@DeptName Relative n 從指針的當(dāng)前位置移動(dòng)n行。如果n是正值,DBMS將行指針向后或向下移動(dòng)至第n行;如果n是負(fù)數(shù),則DBMS將行指針向前或向上移動(dòng)n行; Fetch Relative 2 From cur_Depart Into @DeptID,@DeptName 3)基于游標(biāo)的定位DELETE/UPDATE語句 如果游標(biāo)是可更新的(也就是說,在定義游標(biāo)語句中不包括Read Only 參數(shù)),就可以用游標(biāo)從游標(biāo)數(shù)據(jù)的源表中DELETE/UPDATE行,即DELETE/UPDATE基于游標(biāo)指針的當(dāng)前位置的操作; 舉例: –刪除當(dāng)前行的記錄 Declare cur_Depart Cursor For Select cDeptID,cDeptName From Department into @DeptID,@DeptName Open cur_Depart Fetch From cur_Depart into @DeptID,@DeptName Delete From Department Where CURRENT OF cur_Depart –更新當(dāng)前行的內(nèi)容 Declare cur_Depart Cursor For Select cDeptID,cDeptName From Department into @DeptID,@DeptName Open cur_Depart Fetch From cur_Depart into @DeptID,@DeptName Update Department Set cDeptID=’2007′ + @DeptID Where CURRENT OF cur_Depart 3.游標(biāo)使用技巧及注意 1)利用Order By改變游標(biāo)中行的順序。此處應(yīng)該注意的是,只有在查詢的中Select 子句中出現(xiàn)的列才能作為Order by子句列,這一點(diǎn)與普通的Select語句不同; 2)當(dāng)語句中使用了Order By子句后,將不能用游標(biāo)來執(zhí)行定位DELETE/UPDATE語句;如何解決這個(gè)問題,首先在原表上創(chuàng)建索引,在創(chuàng)建游標(biāo)時(shí)指定使用此索引來實(shí)現(xiàn);例如: Declare cur_Depart Cursor For Select cDeptID,cDeptName From Department With INDEX(idx_ID) For Update Of cDeptID,cDeptName 通過在From子句中增加With Index來實(shí)現(xiàn)利用索引對(duì)表的排序; 3)在游標(biāo)中可以包含計(jì)算好的值作為列; 4)利用@@Cursor_Rows確定游標(biāo)中的行數(shù); ALTER FUNCTION SEL_KEYAR(@YEARNUM INT,@f_k_lessonid VARCHAR(15)) RETURNS VARCHAR(8000) AS BEGIN DECLARE @NIAN VARCHAR(8000),@NUMS INT,@NIANS VARCHAR(8000) SET @NUMS=1 DECLARE GETYEAR CURSOR FOR SELECT f_year FROM t_kejianol WHERE f_k_lessonid=@f_k_lessonid GROUP BY f_year ORDER BY f_year DESC OPEN GETYEAR FETCH NEXT FROM GETYEAR INTO @NIAN WHILE @@FETCH_STATUS=0 BEGIN IF @YEARNUM=@NUMS SET @NIANS=ISNULL(@NIANS+’,’,”)+RTRIM(@NIAN) SELECT @NUMS=@NUMS+1 FETCH NEXT FROM GETYEAR INTO @NIAN –FETCH ABSOLUTE 3 FROM GETYEAR INTO @NIAN END CLOSE GETYEAR DEALLOCATE GETYEAR –PRINT @NIANS RETURN @NIANS END ALTER FUNCTION SEL_KEYAR(@YEARNUM INT,@f_k_lessonid VARCHAR(15)) RETURNS VARCHAR(8000) AS BEGIN DECLARE @NIAN VARCHAR(8000),@NIANS VARCHAR(8000) DECLARE GETYEAR CURSOR FOR SELECT f_year FROM t_kejianol WHERE f_k_lessonid=@f_k_lessonid GROUP BY f_year ORDER BY f_year ASC OPEN GETYEAR FETCH ABSOLUTE @YEARNUM FROM GETYEAR INTO @NIAN CLOSE GETYEAR DEALLOCATE GETYEAR RETURN @NIANS END