mysql常用操作語法(十四)~~複雜的存儲過程

前言

我看到在很多教程中,都是把存儲過程和自定義函數一起講,主要是因爲他們兩個非常的相像,而且自定義函數從某種程度上講,更像是存儲過程中的特例。
在這種情況下,我就暫時省略掉自定義函數的筆記,直接繼續瞭解更復雜的存儲過程。
所謂的更復雜,實際上也就是定義變量,變量賦值,遊標以及結構控制語句和循環等,有java語言基礎的情況下,就很好理解了,只是其中有些細節需要稍微注意一下。

定義變量和賦值

之前的例子中,在存儲過程裏只是簡單地做一些基本sql操作,而實際應用中自然遠不止這麼簡單,經常需要聲明變量,並進行一定的操作。
聲明變量的語法是:

DECLARE 變量名 變量類型  約束條件

例如:

DECLARE count INTEGER DEFAULT 100;

給變量賦值的常用語法是:

SET 變量名 = 值;

例如:

SET count = 10;

上邊賦值的語法比較常用,但是還有其他的語法也可以賦值,例如:

SELECT COUNT(*) INTO COUNT FROM USER;

上邊這種根據sql語句的結果進行賦值需要注意的是,當前sql返回值必須是單一的而不能是多個。

結構控制

結構控制我目前瞭解的有兩種,使用if和case,結合上邊變量的知識以及之前存儲過程一起舉例進行說明:

DELIMITER $
CREATE PROCEDURE proce_test0()
BEGIN
DECLARE COUNT INTEGER DEFAULT 0;
DECLARE result VARCHAR(10) DEFAULT '';
SELECT COUNT(*) INTO COUNT FROM USER;
IF COUNT 

遊標

在上邊的例子中,我們聲明瞭變量,並且把sql語句的結果賦值給了變量,但是這裏的問題就是隻能把單結果的sql賦值給變量。如果要把一個結果集賦值給某個變量進行操作,就需要藉助遊標實現,例如:

DELIMITER $
CREATE PROCEDURE proce_test0()
BEGIN

DECLARE user_id INTEGER;
DECLARE cursor_userId CURSOR FOR SELECT id FROM USER;
OPEN cursor_userId;
FETCH cursor_userId INTO user_id;
SELECT user_id;
CLOSE cursor_userId;

END
$
DELIMITER ;

對上述示例的紅色標記部分解釋如下:
聲明一個user_id變量,類型是INTEGER;
創建一個遊標,名稱是cursor_userId,遊標裏的內容是user表中的id結果集;
打開遊標;
從遊標當前位置取出一條數據,賦值給變量user_id,並把遊標向前移動一位;
輸出變量user_id的值;
關閉遊標。

循環

上述示例中,只是從遊標中取出了一條數據,如果要取出所有數據,比較好的方法就是使用循環遍歷,有while、loop以及repeat,例如:

DELIMITER $
CREATE PROCEDURE proce_test0()
BEGIN

DECLARE user_id INTEGER;
DECLARE flag INTEGER DEFAULT 0;
DECLARE idStr NVARCHAR(20) DEFAULT '';
DECLARE cursor_userId CURSOR FOR SELECT id FROM USER;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET flag = 1;
OPEN cursor_userId;
WHILE flag != 1 DO
FETCH cursor_userId INTO user_id;
IF user_id = 5 THEN
IF idStr = '' THEN
SET idStr = user_id;
ELSE
SET idStr = CONCAT(idStr,'|',user_id);
END IF;
END IF;
END WHILE;
CLOSE cursor_userId;
SELECT idStr;

END
$
DELIMITER ;

上述存儲過程中,我想做的事是這樣的:
把user表中所有id是5的數據用“|”連接成一個字符串。
對上述紅色部分的解釋是:
聲明一個名稱爲user_id的變量,類型是INTEGER;
聲明一個名稱爲flag的變量,類型是INTEGER,默認值是0。這個變量的作用是作爲while循環的條件;
聲明一個名稱是idStr的變量,類型是varchar,長度20,默認值空字符串;
聲明一個遊標,上邊解釋過;
設置遊標讀取到末尾的時候,改變變量flag的值;
打開遊標;
使用while循環,添加條件flag != 1;
從遊標讀取數據,並移動遊標位置,上邊解釋過;
外層if判斷user_id的值,等於5的時候進入內層if;
內層if判斷idStr是否是空字符串,如果是,就把user_id的值賦值給idStr,也就是第一個id前邊不要“|”,否則進行字符串拼接;
結束內層if;
結束外層if;
結束while循環;
關閉遊標;
輸出變量idStr的值。

上邊的存儲過程把while循環替換成loop循環之後如下:

DELIMITER $
CREATE PROCEDURE proce_test0()
BEGIN
DECLARE user_id INTEGER;
DECLARE flag INTEGER DEFAULT 0;
DECLARE idStr NVARCHAR(20) DEFAULT '';
DECLARE cursor_userId CURSOR FOR SELECT id FROM USER;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET flag = 1;
OPEN cursor_userId;

loop_test:LOOP
IF flag =1 THEN
LEAVE loop_test;
END IF;

FETCH cursor_userId INTO user_id;
IF user_id = 5 THEN
IF idStr = '' THEN
SET idStr = user_id;
ELSE
SET idStr = CONCAT(idStr,'|',user_id);
END IF;
END IF;

END LOOP;

CLOSE cursor_userId;
SELECT idStr;
END
$
DELIMITER ;

重點在紅色部分,其中loop_test是自定義的名字,可以理解成java中for循環前的標籤。然後需要if判斷一個臨界條件來終止循環,終止的語法就是leave 循環名,相當於java的for循環裏的break。最後的end loop結束循環。

同樣的,上邊的寫法也可以用repeat循環來代替:

DELIMITER $
CREATE PROCEDURE proce_test0()
BEGIN
DECLARE idStr VARCHAR(20) DEFAULT '';
DECLARE user_id INTEGER;
DECLARE flag INTEGER DEFAULT 0;
DECLARE cursor_id CURSOR FOR SELECT id FROM USER;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET flag = 1;
OPEN cursor_id;

REPEAT

FETCH cursor_id INTO user_id;
IF user_id =5 THEN
IF idStr = '' THEN
SET idStr = user_id;
ELSE
SET idStr = CONCAT(idStr,"|",user_id);
END IF;
END IF;

UNTIL flag =1 END REPEAT;

CLOSE cursor_id;
SELECT idStr;
END
$
DELIMITER ;

repeat循環的終止,需要藉助於until關鍵字,這種語法結構的寫法其實很像是java中的do while循環,先給一個關鍵詞,然後是循環體,最後寫終止循環的條件。

通過上邊的示例,就可以基本瞭解變量聲明和賦值,結構控制語句,遊標,循環等語法的用法,從而組合起來生成相對複雜的存儲過程了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章