MySQL必知必會——第24章 使用遊標 讀書筆記

本章講授了什麼是遊標,如何使用遊標。
1 什麼是遊標
遊標只用於MySQL5.0及以後的版本。
MySQL檢索操作返回一組稱爲結果集的行。這組返回的行都是與SQL語句相匹配的行(零行或者多行)。
使用簡單的select語句沒有辦法得到第一行、下一行或前10行,也不存在每次一行地處理所有行的簡單方法(相對於成批地處理它們)。
有時,需要在檢索出來的行中前進或後退一行或多行。這就是使用遊標的原因。
遊標是一個存儲在MySQL服務器上的數據庫查詢,它不是一條select語句,而是被該語句檢索出來的結果集
在存儲了遊標之後,應用程序可以根據需要滾動或瀏覽其中的數據。
遊標主要用於交互式應用,其中用戶需要滾動屏幕上的數據,並對數據進行瀏覽或更改。
MySQL遊標只能用於存儲過程。
2 使用遊標
步驟:①在能夠使用遊標前,必須聲明它。這個過程實際上沒有檢索數據,它只是定義要使用的select語句。
②一旦聲明後,必須打開遊標以供使用。這個過程用前面定義的select語句把數據實際檢索出來。
③對於填有數據的遊標,根據需要取出(檢索)各行。
④在結束遊標使用後,必須關閉遊標。
在聲明遊標後,可根據需要頻繁地打開和關閉遊標。在遊標打開後,可根據需要頻繁地執行取操作。
(1)創建遊標
遊標用declare語句創建。declare命名遊標,並定義相應的select語句,根據需要帶where和其他子句。
例如,下面語句定義了名爲ordernumbers的遊標,使用了可以檢索所有訂單的select語句。

create procedure processorders()
begin
  declare ordernumbers cursor
  for
  select order_num from orders;
end;

這個存儲過程並沒有做很多事情,declare語句用來定義和命名遊標,這裏爲ordernumbers。存儲過程完成後,遊標就消失(遊標僅限於存儲過程)。
在定義遊標後,可以打開它。
(2)打開和關閉遊標
遊標用open cursor語句來打開:

open ordernumbers;

處理open語句時執行查詢,存儲檢索出的數據以供瀏覽和滾動。
遊標處理完成後,使用如下語句關閉遊標:

close ordernumbers;

close釋放遊標使用的所有內部內存和資源,因此每個遊標不再使用時都應該關閉。
在一個遊標關閉後,如果沒有重新打開, 則不能使用它。但是,使用聲明過的遊標不需要再次聲明,用open語句打開它就可以了。
隱含關閉:如果你不明確關閉遊標,MySQL將會在到達end語句時自動關閉它。
下面是前面例子的修改版本:

create procedure processorders()
begin
  --declare the cursor
  declare ordernumbers cursor
  for 
  select order_num from orders;
  --open the cursor
  open ordernumbers;
  --close the cursor
  close ordernumbers;
end;

這個存儲過程聲明、打開和關閉一個遊標。但對檢索出的數據什麼也沒做。
(3)使用遊標數據
在一個遊標被打開時,可以使用fetch語句分別訪問它的每一行。fetch指定檢索什麼數據(所需的列),檢索出來的數據存儲在什麼地方。它還向前移動遊標中的內部行指針,使下一條fetch語句檢索下一行(不重複讀取同一行)。
第一個例子從遊標中檢索單個行(第一行)。

create procedure processorders()
begin
--declare local variable
declare  o int;
--declare the cursor
declare ordernumbers cursor
for
select order_num from orders;

--open the cursor
open ordernumbers;
--get order number
fetch ordernumbers into o;
--close the cursor
close ordernumbers;
end;

其中fetch用來檢索當前行的order_num列(將自動從第一行開始)到一個名爲o的局部聲明的變量中。對檢索出的數據不做任何處理。
在下一個例子中,循環檢索數據,從最後一行到第一行:

create procedure processorders()
begin
--declare local variable 
declare done boolean default 0;
declare o int;
--declare the cursor
declare ordernumbers cursor
for 
select order_num from orders;
--open the cursor
open ordernumbers;
--loop through all done
repeat
--get order number
fetch ordernumbers into o;
--end of loop
until done end repeat;
--close the cursor
close ordernumbers;
end;

與前面一個例子一樣,這個例子使用fetch檢索當前order_num到聲明爲o的變量中。但與前一個例子不同的是,這個fetch是在repeat內,因爲它反覆執行直到done爲真(由until done end repeat;規定)。爲了使它起作用,用一個default 0來定義變量done。那麼done怎樣才能在結束時被設置爲真呢?答案是用以下語句:

declare continue handler for SQLSTATE '02000' SET done=1;

這個語句定義了一個continue handler,它是在條件出現時被執行的代碼。當SQLSTATE‘02000’出現時,set done=1。SQLSTATE’02000’是一個未找到條件,當REPEAT由於沒有更多的行供循環而不能繼續時,出現這個條件。
declare語句的次序:declare語句的發佈存在特定的次序。用declare定義的局部變量必須在定義任意遊標或句柄之前定義,而句柄必須在遊標之後定義。不遵守此順序將產生錯誤消息。
如果調用這個存儲過程,它將定義幾個變量和一個continue handler,定義並打開一個遊標,重複讀取所有行,然後關閉遊標。
如果一切正常,你可以在循環內放入任意需要的處理(在fetch語句之後,循環結束之前)
爲了把這些內容組織起來,下面給出我們的遊標存儲過程樣例的更進一步修改的版本,這次對取出的數據進行某些實際的處理:

create procedure processorders()
begin
--declare local variables
declare done boolean default 0;
declare o int;
declare t decimal(8,2);
--declare the cursor
declare ordernumbers cursor
for
select order_num from orders;
--declare continue handler
declare continue handler for sqlstate '02000' set done=1;
--create a table to store the results
create table if not  exists ordertotals(order_num int,total decimal(8,2));
--open the cursor
open ordernumbers;
--loop through all rows
repeat
--get order numbers
fetch ordernumbers into o;
--get the total for this order
call ordertotal(o,1,t);
--insert order and total into ordertotals
insert into ordertotals(order_num,total) values(o,t);
--end of loop
until done end repeat;
--close the cursor
close ordernumbers;
end;

在這個例子中,我們增加了另一個名爲t的變量(存儲每個訂單的合計)。
此存儲過程還在運行中創建了一個新表ordertotals。這個表將保存存儲過程中生成的結果。
fetch像以前一樣取每一個order_num,然後用call執行另一個存儲過程(前一章中創建)來計算每個訂單的帶稅的合計(結果存儲到t)。
最後用insert保存每個訂單的訂單號和合計。
此存儲過程不返回數據,但它能創建和填充另一個表,可以用select語句查看錶的內容:

select * from ordertotals;

這樣我們就得到了存儲過程
遊標、逐行處理以及存儲過程調用其他存儲過程的一個完整的工作樣例。

小結
本章介紹了什麼是遊標、爲什麼要使用遊標,說明了基本遊標使用的例子,講解了對遊標結果進行循環以及逐行處理的技術。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章