游標
游標(Cursor)是用於查看或者處理結果集中的數據的一種方法。游標提供了在結果集中一次一行或者多行前進或向后瀏覽數據的能力。
游標的使用方式
- 定義游標:Declare 游標名稱 CURSOR for table;(table也可以是select出來的結果集)
- 打開游標:Open 游標名稱;
- 從結果集獲取數據到變量:fetch 游標名稱 into field1,field2;
- 執行語句:執行需要處理數據的語句
- 關閉游標:Close 游標名稱;
BEGIN
# 聲明自定義變量
declare c_stgId int;
declare c_stgName varchar(50);
# 聲明游標結束變量
declare done INT DEFAULT 0;
# 聲明游標 cr 以及游標讀取到結果集最后的處理方式
declare cr cursor for select Name,StgId from StgSummary limit 3;
declare continue handler for not found set done = 1;
# 打開游標
open cr;
# 循環
readLoop:LOOP
# 獲取游標中值並賦值給變量
fetch cr into c_stgName,c_stgId;
# 判斷游標是否到底,若到底則退出游標
# 需要注意這個判斷
IF done = 1 THEN
LEAVE readLoop;
END IF;
SELECT c_stgName,c_stgId;
END LOOP readLoop;
-- 關閉游標
close cr;
END
聲明變量Declare語句注意點:
- Declare語句通常用來聲明本地變量、游標、條件或者handler
- Declare語句只允許出現在
BEGIN...END
語句中而且必須出現在第一行 - Declare的順序也有要求,通常是先聲明本地變量,再是游標,然后是條件和handler
自定義變量命名注意點:
自定義變量的名稱不要和游標的結果集字段名一樣。若相同會出現游標給變量賦值無效的情況。
臨時表
臨時表只在當前連接可見,當關閉連接時,Mysql會自動刪除表並釋放所有空間。因此在不同的連接中可以創建同名的臨時表,並且操作屬於本連接的臨時表。
與普通創建語句的區別就是使用 TEMPORARY 關鍵字
CREATE TEMPORARY TABLE StgSummary(
Name VARCHAR(50) NOT NULL,
StgId INT NOT NULL DEFAULT 0
);
臨時表使用限制
- 在同一個query語句中,只能查找一次臨時表。同樣在一個存儲過程中也不能多次查詢臨時表。但是不同的臨時表可以在一個query中使用。
- 不能用RENAME來重命名一個臨時表,但是可以用ALTER TABLE代替
ALTER TABLE orig_name RENAME new_name;
- 臨時表使用完以后需要主動Drop掉
DROP TEMPORARY TABLE IF EXISTS StgTempTable;
存儲過程中使用游標循環讀取臨時表數據
BEGIN
## 創建臨時表
CREATE TEMPORARY TABLE if not exists StgSummary(
Name VARCHAR(50) NOT NULL,
StgId INT NOT NULL DEFAULT 0
);
TRUNCATE TABLE StgSummary;
## 新增臨時表數據
INSERT INTO StgSummary(Name,StgId)
select '臨時數據',1
BEGIN
# 自定義變量
declare c_stgId int;
declare c_stgName varchar(50);
declare done INT DEFAULT 0;
declare cr cursor for select Name,StgId from StgSummary ORDER BY StgId desc LIMIT 3;
declare continue handler for not found set done = 1;
-- 打開游標
open cr;
testLoop:LOOP
-- 獲取結果
fetch cr into c_stgName,c_stgId;
IF done = 1 THEN
LEAVE testLoop;
END IF;
SELECT c_stgName,c_stgId;
END LOOP testLoop;
-- 關閉游標
close cr;
End;
DROP TEMPORARY TABLE IF EXISTS StgSummary;
End;
最開始的時候,先創建臨時表,再定義游標。但是存儲過程無論如何都保存不了。直接報錯You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'DECLARE ...
。根本原因就是上面提到的注意點(Declare語句只允許出現在BEGIN...END
語句中而且必須出現在第一行)。所以最后只能多個加一對BEGIN...END
進行隔開。
總結
以前寫SQL Server的存儲過程,沒有仔細注意過這個問題,定義變量一般都在程序中部,MySQL就想當然的隨便寫,最后終於踩坑了。這兩個語法上差別不大,但是真遇到差別還是挺突然的。不過也好久沒有寫SQL語句,有點生疏了啊。還是趕緊把坑給記下來,加深下印象吧。