MYSQL存儲過程常見操作誤區 - 游標(CURSOR) - 函數,過程調用 - 遞歸操作


這兩天在做一些簡單的存儲過程,以前並未涉及過,現學現賣,碰到了不少問題,找了很多資料,也差不多解決了,廢話不多說,希望用自己的失敗經驗給猿們提供點幫助。

 

  1. select into 導致游標處理未全部完成

    #一般來講,我們會在某個過程(帶有游標或其他循環操作)開始之前定義一個處理完畢的標識

    DECLARE done INT DEFAULT 0;

    #設置游標信息 (以查詢 a 表 id 為實例) 

    DECLARE a_id INT DEFAULT 0; 
    DECLARE b_id INT DEFAULT 0;

    DECLARE cur CURSOR FOR (
      SELECT ` id`  FROM `a_table`;
    );

    #然而一般我們也會在出現錯誤或者其他情況下重置done的值,如下:

    #出現異常(SQLSTATE 02000 | NOT FOUND)
    DECLARE CONTINUE HANDLER for SQLSTATE '02000' SET done = 1;

    #然后開始游標

    OPEN cur;
    #獲取第一層游標
    FETCH cur INTO a_id;

    #開始循環處理(While)

    WHILE (done = 0) DO

      #查詢關聯信息(這句在某些情況下會出現錯誤,導致游標結束)
      SELECT `id` INTO b_id from `b_table` WHERE `a_id` = a_id;

      #獲取下一層游標,並繼續循環
      FETCH cur INTO o_model_name;

    #結束循環處理
    END WHILE;

    #結束游標
  CLOSE cur;

 

  廢話說了這么多,寫了個簡單的例子,簡單的說說會出現問題的原因,正常來說,當b_table中不存在a_id對應的ID值時,將返回null,但由於DECLARE CONTINUE HANDLER for SQLSTATE '02000' SET done = 1;當出現查詢為null的情況時,將會重置done為1,從而不在執行后面的游標,解決方案如下:

  SELECT `id` INTO b_id from `b_table` WHERE `a_id` = a_id;

  更改為

  SET b_id = (SELECT `id` FROM `b_table` WHERE `a_id` = a_id);

  后續邏輯可直接判斷b_id的值

    IF b_id != '' THEN

      #處理邏輯

    END IF;

  2. function(函數) 與 PROCEDURE(過程)的不同調用方法

    function 采用  SELECT 調用,一般會返回返回值,所以最好先定義一個變量用於儲存返回值(如果需要),如帶參數可直接對應賦值參數即可。

    DECLARE a_result VARCHAR(100) DEFAULT '';

    SELECT function_A([param_1,param_2]) INTO a_result;

    procedure 采用 CALL 調用,沒有返回值,主要處理邏輯,可傳參數,特別注意的是:請留意 IN ,OUT ,INOUT三種模式,具體區別百度一下,講的比我清楚。

    DECLARE param_1 INT DEFAULT 0;

    CALL procedure_A(param_1);


  3. 遞歸操作

    說實話剛開始使用遞歸是真把我難到了,網上也沒有准確的操作方法,慢慢摸索才理清楚,這里也不出例子了,其實就是結合function(函數) 與 PROCEDURE(過程)就能完美的呈現遞歸操作,這里強調一點,當遞歸操作時,一般會報

    ERROR 1456 (HY000): Recursive limit 0 (as set by the max_sp_recursion_depth variable) was exceeded for routine

    等錯誤,那是因為默認情況下是不允許使用遞歸操作的,這里需要在需要遞歸操作前生命一個系統變量:
    
    SET @@max_sp_recursion_depth = 100;
    
    后面的數值根據自己的情況設置,表示想要遞歸的層級


    總結:新熟悉一個東西都會有很大的難度,但是網上已經有很多前輩給的方法解決,大家一定要多動手多了解,可能我這里有說的錯誤的地方,希望多多理解,有問題就回復,我好更改,哈哈。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM