Navicat中如何調試存儲過程

存儲過程調試方法

參考

https://www.cnblogs.com/firebata/p/4585978.htmlhtml

https://www.cnblogs.com/kungfupanda/p/5645553.html框架

調試很是麻煩

如何在存儲過程當中註釋?

在存儲過程編輯中沒法註釋,因此須要先將代碼拷貝到普通查詢頁,在查詢頁註釋好,而後再將代碼拷貝回存儲過程當中,保存。oop

變量定義

定義varchar變量必須指明大小

如varchar(10),不然會報錯測試

遊標須要定義在全部其餘變量以後,不然會報 1337 錯誤

ERROR 1337 (42000): Variable or condition declaration after cursorfetch

變量的定義不要和你的select的列的鍵同名!否則,fetch into 會失敗!

這個沒試,可是名字最好不要和列名同名,這樣也更易讀。spa

語法方面

存儲過程當中必定要記得在語句後面加上分號「;」,不然會報看起來莫名其妙的錯誤

調試技巧:可使用 SELECT @a 查看打印的變量,可是注意 @a看到的是最終的變量,中間變量是沒法看到的

使用 SELECT @a看到的結果中的 @a 值是最終值,中間變量是沒法看到的,因此說調試很是麻煩,沒法打印變量在運行中間的值.net

★調試的技巧

也是定位錯誤的方法(由於根據提示的錯誤很難定位到錯誤的語句位置):刪除無關的語句,排除的方法。設計

邊開發邊測試:(1)設計好總體思路;(2)將思路框架寫出來,先不要填充細節部分,好比有的複雜的實現,能夠先空着或者簡單的打印一些變量,邊寫邊測,及時發現各類問題;(3)思路框架寫出來後,若是測試沒有問題,再補充細節代碼,最好寫一部分就測試一下。由於調試太麻煩的緣由,這樣比較穩妥。調試

遊標的使用

參考

https://www.cnblogs.com/trying/p/3296793.htmlhtm

使用

遊標須要定義在全部其餘變量以後,不然會報 1337 錯誤

如何循環?

如何結束?

如何調試?調試很是麻煩

遊標使用示例存儲過程1

背景說明

將表t中的數據拷貝至表t1

建表語句

-- ----------------------------

-- Table structure for t

-- ----------------------------

DROP TABLE IF EXISTS `t`;

CREATE TABLE `t` (

  `i` int(11) DEFAULT NULL

) ENGINE=InnoDB DEFAULT CHARSET=utf8;

 

-- ----------------------------

-- Records of t

-- ----------------------------

INSERT INTO `t` VALUES ('1');

INSERT INTO `t` VALUES ('2');

 

-- ----------------------------

-- Table structure for t1

-- ----------------------------

DROP TABLE IF EXISTS `t1`;

CREATE TABLE `t1` (

  `i` int(11) DEFAULT NULL

) ENGINE=InnoDB DEFAULT CHARSET=utf8;

 

存儲過程testCopy

-- ----------------------------

-- Procedure structure for testCopy

-- ----------------------------

DROP PROCEDURE IF EXISTS `testCopy`;

DELIMITER ;;

CREATE DEFINER=`root`@`localhost` PROCEDURE `testCopy`()

BEGIN

-- 須要定義接收遊標數據的變量

  DECLARE a CHAR(16);

  

  -- 遍歷數據結束標誌

  DECLARE done INT DEFAULT FALSE;

-- 遊標,遊標須要定義在全部其餘變量以後,不然會報 1337 錯誤

  DECLARE cur CURSOR FOR SELECT i FROM t;

  -- 將結束標誌綁定到遊標

  DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;

 

  -- 打開遊標

  OPEN cur;

  

  -- 開始循環

  read_loop: LOOP

    -- 提取遊標裏的數據,這裏只有一個,多個的話也同樣;

    FETCH cur INTO a;

    -- 聲明結束的時候

    IF done THEN

      LEAVE read_loop;

    END IF;

    -- 這裏作你想作的循環的事件

 

    INSERT INTO t1 VALUES (a);

 

  END LOOP;

  -- 關閉遊標

  CLOSE cur;

 

END

;;

DELIMITER ;

遊標使用示例存儲過程2

建表語句

-- ----------------------------

-- Table structure for current

-- ----------------------------

DROP TABLE IF EXISTS `current`;

CREATE TABLE `current` (

  `player` varchar(11) DEFAULT NULL,

  `market` varchar(11) DEFAULT NULL,

  `money` int(11) DEFAULT NULL,

  `dateno` int(11) DEFAULT NULL

) ENGINE=InnoDB DEFAULT CHARSET=utf8;

 

-- ----------------------------

-- Records of current

-- ----------------------------

INSERT INTO `current` VALUES ('小明', '永輝', '100', '20190807');

INSERT INTO `current` VALUES ('小明', '物美', '200', '20190807');

INSERT INTO `current` VALUES ('小剛', '家樂福', '230', '20190807');

 

-- ----------------------------

-- Table structure for history

-- ----------------------------

DROP TABLE IF EXISTS `history`;

CREATE TABLE `history` (

  `player` varchar(11) DEFAULT NULL,

  `market` varchar(11) DEFAULT NULL,

  `money` int(11) DEFAULT NULL,

  `dateno` int(11) DEFAULT NULL

) ENGINE=InnoDB DEFAULT CHARSET=utf8;

 

-- ----------------------------

-- Records of history

-- ----------------------------

背景說明

表current,表history

結構一致,均爲

player 送貨員

market 超市

money 送貨錢數

dateno 日期序號

想象一個送貨員能夠幫多家超市(永輝、物美、家樂福等)送貨,每次送貨都會是必定的金額(從幾十元到幾百上千元)。

current記錄的是今天某個送貨員給給家送貨的金額狀況。

history記錄的今天以前的累計狀況。

那麼存儲過程testMerge就是執行這麼個操做:將current表中的數據累計到history表中,而後刪除累計過的數據。

思路:(1)選取current表中符合條件的記錄到遊標;(2)操做遊標,看是往history表中插入記錄,仍是更新history表中的記錄;(3)操做完畢關閉遊標。

往history表中插入記錄,仍是更新history表中的記錄的判斷條件:使用【送貨員,超市】聯合鍵判斷,history中存在【送貨員,超市】聯合鍵,則將current中的送貨錢數累加到以前的記錄;history中不存在【送貨員,超市】聯合鍵,則向history中新增一條記錄。

暫時只是測試例子,實際可繼續完善。

存儲過程testMerge

-- ----------------------------

-- Procedure structure for testMerge

-- ----------------------------

DROP PROCEDURE IF EXISTS `testMerge`;

DELIMITER ;;

CREATE DEFINER=`root`@`localhost` PROCEDURE `testMerge`()

BEGIN

-- 須要定義接收遊標數據的變量

  DECLARE player_param VARCHAR(10);

DECLARE market_param VARCHAR(10);

DECLARE money_param INT;

 

DECLARE exist_record INT;

  

  -- 遍歷數據結束標誌

  DECLARE done INT DEFAULT FALSE;

-- 遊標,遊標須要定義在全部其餘變量以後,不然會報 1337 錯誤

  DECLARE record_list CURSOR FOR

SELECT

player,

market,

money

FROM

current

WHERE

dateno < 20190808;

  -- 將結束標誌綁定到遊標

  DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;

 

  -- 打開遊標

  OPEN record_list;

  

  -- 開始循環

  read_loop: LOOP

    -- 提取遊標裏的數據,這裏只有一個,多個的話也同樣;

    FETCH record_list INTO player_param,market_param,money_param;

    -- 聲明結束的時候

    IF done THEN

      LEAVE read_loop;

    END IF;

 

SELECT COUNT(*) INTO @exist_record FROM history WHERE player = player_param AND market = market_param;

 

IF @exist_record = 0 THEN

    -- 這裏作你想作的循環的事件

INSERT INTO history VALUES (player_param,market_param,money_param,0);

END IF;

 

IF @exist_record > 0 THEN

UPDATE history SET money = money + money_param WHERE player = player_param AND market = market_param;

END IF;

 

DELETE FROM current WHERE dateno = 20190807;

 

  END LOOP;

  -- 關閉遊標

  CLOSE record_list;

 

END

;;

DELIMITER ;

相關文章
相關標籤/搜索