李艷杰
(山東華宇工學院,山東 德州 253034)
數據庫中會經常用到查詢,查詢的結果是符合條件的多條記錄的集合。但有時在查詢時并不需要把所有符合條件的記錄全部取出,或是需要逐條獲取記錄的值,此時普通查詢實現不了,需要用到游標來逐條讀取記錄值,并對逐條記錄進行使用。在數據庫中,游標是系統為用戶開設的緩沖區域,存放SQL 語句的執行結果,實際上,游標是一種能從包括多條數據記錄結果集中每次提取一條記錄的機制,游標允許應用程序對查詢語句select 返回的行結果集中每一條記錄進行相同或不同的操作,而不是一次對整個結果集進行同一種操作,從而可以發揮每一條記錄的作用。游標通常體現在存儲過程中。
MySQL中使用declare 關鍵字來聲明游標,其語法結構及解釋如下所示:
Declare 游標名稱 cursor for select語句。
注意:關鍵字是不能少的,游標名稱符合標識符的定義即可。select語句根據需求不同,此時內存便分配一塊空間來存儲返回的結果集。這塊空間也可以認為是一個虛表,這個虛表便是游標。
打開游標的關鍵字為open,其語法結構及解釋如下所示:
Open 游標名稱。
打開游標即激活查詢并識別游標,此時游標中的指針指向查詢出的結果集中第一行記錄的前面。
使用游標的關鍵字為fetch和into,其語法結構及解釋如下所示:
Fetch 游標名稱 into 變量。
注意:第一次使用時,指針指向結果集中第一條記錄并提取里面的值,每調用一次,指針會下移一條記錄,此時的變量個數與select語句后面的字段個數一致。
關閉游標的關鍵字為close,其語法結構及解釋如下所示:
Close 游標名稱。
當游標指針指向最后一條記錄之后,即不能提取數據時,此時需要關閉游標,釋放資源,不能再用fetch來提取數據了。
游標是寫在存儲過程中的,有時數據量大,不清楚記錄的行數,此時需要定義處理程序。定義處理程序說明如下:
declare 參數1 handler for 參數2 SQL語句。
參數1:exit退出當前程序,continue 繼續執行程序。
參數2:not found 代表當fetch抓取不到數據時,即游標指針走到最后一條記錄的后面,沒有記錄可以提取了。
SQL語句:set temp=1,注意temp是變量,必須提前聲明,其值只能是0(false)或1(true)。
在ceshi1數據庫下,建表。在create table book1(bid int,shl int,jg float),輸入3條記錄,代碼如下:
Insert into book1 values(102,1,15),(103,3,5) ,(101,2,10);
3.2.1 建立案例anli7
建立存儲過程anli7,獲取book1表中的所有記錄,并逐行獲取進行顯示。代碼和解釋如下:
create procedure anli7() -建立存儲過程;
begin -把語句放到一個begin塊內;
declare a,b int; -聲明變量存放圖書編號和數量;
declare c float; -聲明變量存放圖書價格;
declare c1 cursor for select * from book1; -聲明游標;
open c1; -打開游標;
fetch c1 into a,b,c; -使用游標提取第一條記錄;
select a,b,c; -顯示a,b,c的值;
fetch c1 into a,b,c; -使用游標提取第二條記錄;
select a,b,c; -顯示a,b,c的值;
fetch c1 into a,b,c; -使用游標提取第三條記錄;
select a,b,c; -顯示a,b,c的值;
close c1; -關閉游標;
end // -此語句塊結束。
完成之后,利用語句mysql> call anli7()//,執行存儲過程,顯示第一條記錄的結果如圖1所示:
圖1 執行結果Fig.1 Execution results
此案例中,已經知道了此表中有3條記錄,可以提取3次,假設不知道有幾條記錄,此時的解決辦法是使用循環。由于用到循環,必須考慮循環退出條件,由于無法確定記錄條數,所以退出條件無法寫,需要定義處理程序,即當程序本身發現問題時,會自動去處理。以下用循環實現。
3.2.2 建立案例anli8
用循環獲取book1表中的所有記錄,并逐行獲取進行顯示。
create procedure anli8() -建立存儲過程;
begin -把語句放到一個begin塊內;
declare a,b int; -聲明變量存放圖書編號和數量;
declare c float; -聲明變量存放圖書價格;
declare temp int default 0; -聲明一個變量,默認值為0;
declare c1 cursor for select * from book1; -聲明游標;
declare exit handler for not found set temp=1; -not found代表拿不到數據。即select語句返回值為空。執行set語句,把原來的默認值0改為1,同時退出整個程序。即當游標通過循環取完記錄,最終取不到記錄時,退出循環。
open c1; -打開游標;
repeat -循環語句開始;
fetch c1 into a,b,c; -通過循環使用游標提取每一條記錄;
select a,b,c; -顯示a,b,c的值;
until temp=1 -循環結束條件;
end repeat; -退出循環;
close c1; -關閉游標;
end // --此語句塊結束。
由此可見,通過循環獲取每一條語句程序更簡潔合理,因此在存儲過程中絕大部分的游標是和循環結合使用的。
重點介紹了MySQL數據庫中游標含義和使用游標的步驟及如何高效使用游標,并舉例說明游標的具體使用,以便更方便地使用游標解決現實生活中的問題。