MySQL非源碼學習:關於存儲過程的中遊標兩個容易忽略的點

今天寫個稍微復雜一點點的存儲過程碰到兩個容易忽略的點分享一下。如果有筒子剛好碰到相同的問題可以少再糾結一下, 木有啥技術含量的。。。
 
1、一個存儲過程使用遊標的例子
假設很簡單的一個要求:從t表裡面遍歷出f,然後再到t2表中查找符合條件的記錄打出來。
 
declare stopFlag int;
DECLARE  cur_name CURSOR for f from t;
DECLARE CONTINUE HANDLER FOR NOT FOUND set stopFlag=1;
set stopFlag=0;
open cur_name;
REPEAT
FETCH cur_name INTO temp_f;
begin
   select f3 into my_result from t2 where f2=temp_f  limit 1;
end;
UNTIL stopFlag = 1
END REPEAT;
CLOSE cur_name;
 
2、 點1
假設t表有n條記錄,這個循環體循環n次?
實際上是n+1次。因為到達t的最後一行的時候stopFlag還是1。這個值的修改是在下一次fetch的時候改的,但是改完後就進入begin瞭,沒有再判斷,所以會多執行一次。這多出來的一次的temp_f的值和上一次相同。
 
解決方法:在進入Begin之後再判斷一下stopFlag的值
 
3、 點2
有時候會發現沒有循環到n次循環就退出,什麼原因?
原因是如果select f3 into my_result from t2 where f2=temp_f  limit 1; 條件無法匹配行,在試圖對my_result賦值的時候就會觸發set stopFlag=1; 導致在之後的until判斷的時候滿足退出條件而退出。
 
解決方法:特別小心循環體內部出現的這種語句。如果有的話,在進入begin之後把stopFlag存入一個臨時變量,在until之前把這個臨時變量賦回去就行瞭

作者“追風刀·丁奇”
 

發佈留言