1. 程式人生 > >Mysql(7)---存儲過程

Mysql(7)---存儲過程

rep while 循環 設置 col leave rose express dmi right

Mysql(7)---存儲過程

存儲過程接下來會有三篇相關博客

  • 第一篇存儲過程常用語法。
  • 第二篇存儲過程中的遊標。
  • 第三篇單獨講一個實際開發過程中復雜的真實的案例。

一、概述

1、什麽是存儲過程

概述:簡單的說,就是一組SQL語句集,功能強大,可以實現一些比較復雜的邏輯功能,類似於JAVA語言中的方法;

說明 :存儲過程跟觸發器有點類似,都是一組SQL集,但是存儲過程是主動調用的,且功能比觸發器更加強大,觸發器是某件事觸發後自動調用。

2、優點

  • 提高代碼的重用性
  • 簡化操作
  • 減少了編譯次數並且減少了和數據庫服務器的連接次數,提高了效率

二、delimiter命令

講存儲過程先講下delimiter命令。我們都知道sql語句默認都是以分號‘;‘解釋。如果下select * from test_table;

這個會有一個問題對於存儲過程:

CREATE  PROCEDURE `proc_if`(IN type int)
BEGIN
    DECLARE c varchar(500);
    IF type = 0 THEN
        set c = 'param is 0';
    ELSEIF type = 1 THEN
        set c = 'param is 1';
    ELSE
        set c = 'param is others, not 0 or 1';
    END IF;
    select c;
END;

對於上面的存儲過程,它們應該是一個整體,應該是一起執行,而不是遇到分號就執行。默認情況下,不可能等到用戶把這些語句全部輸入完之後,再執行整段語句。 因為mysql一遇到分號,它就要自動執行。 即,在語句遇到‘;‘時,mysql解釋器就要執行了。 這種情況下,就需要事先把delimiter換成其它符號,如//或$$。

這個時候delimiter命令就起作用了。

示例

# 這路我們講默認的 ; 結尾改成 $ 再執行下面語句
DELIMITER $
select * from mall_pro ;
select * from member ;

會發現能之前能正常執行的語句這裏報錯了,因為現在修改結尾標誌為 $

技術分享圖片

如果我們改成:

select * from mall_pro $
select * from member $

技術分享圖片

重點:delimiter作用域是會話級別的,當你設置了DELIMITER $那麽在當前會話級別都是變成以$結束。

附一個詳細講delimiter的博客:MySql中 delimiter 詳解


三、存儲過程語法

1、創建

CREATE PROCEDURE 存儲過程名(參數列表)
BEGIN
     # 存儲過程體(一組合法的SQL語句)
END

2、參數說明

1) 參數列表包含三部分
參數模式 參數名 參數類型
舉例:

in stuname varchar(20)

也可以寫成stuname varchar(20) 但最好把 in 加上。
2) 參數模式

in:該參數可以作為輸入,也就是該參數需要調用方傳入值。
out:該參數可以作為輸出,也就是該參數可以作為返回值。
inout:該參數既可以作為輸入又可以作為輸出,也就是該參數既需要傳入值,又可以返回值。

3、調用

CALL 存儲過程名(實參列表);

4、刪除

如果存在該存儲過程 則刪除該存儲過程。

drop procedure if exists 存儲過程名稱

重點:存儲過程體中的每條sql語句的結尾要求必須加分號

註意:如果存儲過程體僅僅只有一句話,begin end可以省略。

註意:存儲過程的結尾可以使用 delimiter 重新設置(一般如果存儲過程中存在多個分號結尾,就可以使用delimiter)

5、示例

1)空參列表

# 案例:插入到admin表中五條記錄
DELIMITER $
CREATE PROCEDURE myp1()
BEGIN
    INSERT INTO admin(username,`password`) 
    VALUES('john1','0000'),('lily','0000'),('rose','0000'),('jack','0000'),('tom','0000');
END $
# 調用
CALL myp1()$

2):創建帶in模式參數的存儲過程

## 創建存儲過程實現 根據女神名,查詢對應的男神信息
CREATE PROCEDURE myp2(IN beautyName VARCHAR(20))
BEGIN
    SELECT bo.*
    FROM boys bo
    RIGHT JOIN beauty b ON bo.id = b.boyfriend_id
    WHERE b.name=beautyName;
END $
#  調用
CALL myp2('柳巖')$

3) :創建存儲過程實現,用戶是否登錄成功

CREATE PROCEDURE myp4(IN username VARCHAR(20),IN PASSWORD VARCHAR(20))
BEGIN
    DECLARE result INT DEFAULT 0;# 聲明並初始化
    SELECT COUNT(*) INTO result# 賦值
    FROM admin
    WHERE admin.username = username
    AND admin.password = PASSWORD;
    SELECT IF(result>0,'成功','失敗');# 使用
END $
# 調用
CALL myp3('張飛','8888')$

4) 帶有IN 和 OUT 參數

CREATE PROCEDURE myp7(IN beautyName VARCHAR(20),OUT boyName VARCHAR(20),OUT usercp INT) 
BEGIN
    SELECT boys.boyname ,boys.usercp INTO boyname,usercp
    FROM boys 
    RIGHT JOIN
    beauty b ON b.boyfriend_id = boys.id
    WHERE b.name=beautyName ;
END $
# 調用
CALL myp7('小昭',@name,@cp)$ # 註意OUT的變量一定要是用戶自定義的用戶變量。
SELECT @name,@cp$

5) 創建帶inout模式參數的存儲過程

# 傳入a和b兩個值,最終a和b都翻倍並返回
DELIMITER $
CREATE PROCEDURE myp8(INOUT a INT ,INOUT b INT)
BEGIN
    SET a=a*2;
    SET b=b*2;
END $
# 調用
SET @m=10$
SET @n=20$
CALL myp8(@m,@n)$
# 輸出 20 和 40
SELECT @m,@n$

這裏都是舉了寫簡單的例子,後面會根據實際開發過程寫一個復雜的存儲過程。


三、流程控制結構

我們知道java對於流程控制有:if、switch。對於Mysql也一樣,它有它自己的流程控制語句,下面我們一個一個來分析。

1、IF語句

1) if函數

語法:if(條件,值1,值2)
功能:實現雙分支
應用在begin end中或外面

2) if結構

# 如果expression為true 執行 statements
IF expression THEN 
   statements;
END IF;  # 有IF一定要有 END IF

# 如果expression為true 執行 statements 否則執行else-statements
IF expression THEN
   statements;
ELSE
   else-statements;
END IF;

# 不說了。
IF expression THEN
   statements;
ELSEIF elseif-expression THEN
   elseif-statements;
...
ELSE
   else-statements;
END IF;

重點:IF結構最後都需要END IF;結尾。

3)示例

DELIMITER $
CREATE PROCEDURE test_if(score FLOAT) 
BEGIN
    DECLARE ch CHAR DEFAULT 'A';
    IF score>90 THEN SET ch='A';
    ELSEIF score>80 THEN SET ch='B';
    ELSEIF score>60 THEN SET ch='C';
    ELSE SET ch='D';
    END IF;
    select ch;  
END $

call test_if(87)
#輸出 B

2.case結構

1、語法

#情況1:類似於switch
case 變量或表達式
when 值1 then 語句1;
when 值2 then 語句2;
...
else 語句n;
end 

#情況2:
case 
when 條件1 then 語句1;
when 條件2 then 語句2;
...
else 語句n;
end 
#應用在begin end 中或外面

2、示例

DELIMITER $
CREATE PROCEDURE test_case(in score FLOAT) 
BEGIN 
    DECLARE ch CHAR DEFAULT 'A';
    CASE 
    WHEN score>90 THEN SET ch='A';
    WHEN score>80 THEN SET ch='B';
    WHEN score>60 THEN SET ch='C';
    ELSE SET ch='D';
    END CASE;   
    select ch;
END $

call test_case(56)$
# 輸出 D


五、循環結構

對於java循環結構有:for、while、do-while。而對於mysql則有:while、loop、repeat

還有很重要的一點,對於java跳出循環有:continue 和 break。對於mysql也有自己跳出循環命令。

iterate: 類似於 continue,繼續,結束本次循環,繼續下一次
leave:   類似於  break,跳出,結束當前所在的循環
# 至於它們怎麽用,下面會舉例說明

1.while

特點:先判斷後執行。(相當於java中while)

1)語法

【標簽:】while 循環條件 do
    循環體;
 end while【 標簽】;
 # 當你需要用到 iterate 或者 leave 時就需要用到標簽。如果不需要用到這兩個那麽可以不需要標簽

2)示例

#案例:1+2+...100
DELIMITER $
drop procedure if exists `pro_while1` $
CREATE PROCEDURE pro_while1(IN insertCount INT)
BEGIN
    DECLARE total INT DEFAULT 0;
    DECLARE i INT DEFAULT 1;
    WHILE i<=insertCount DO
        set total:=total+i;
        SET i=i+1;
    END WHILE;
    select total;
END $

# 輸出:5050
CALL pro_while1(100)$

3)帶有leave語句示例

#案例:1+2+...100
DELIMITER $
drop procedure if exists `pro_while1` $
CREATE PROCEDURE pro_while1(IN insertCount INT)
BEGIN
    DECLARE total INT DEFAULT 0;
    DECLARE i INT DEFAULT 1;
    a:WHILE i<=insertCount DO
          IF i=11 THEN  LEAVE a; #當i=11是跳出循環 這裏就需要用到標簽了
          END IF;
    set total:=total+i;
    SET i=i+1;
    END WHILE a;
    select total;
END $

# 輸出:55
CALL pro_while1(100)$

這裏就用到標簽(這裏為a)了。

2、repeat

1) 語法

特點:先執行後判斷。(相當於Do-while)

【標簽:】repeat
    循環體;
until 結束循環的條件
end repeat 【標簽】;

2)示例

#案例:1+2+...100
DELIMITER $
drop procedure if exists `pro_while1` $
CREATE PROCEDURE pro_while1(IN insertCount INT)
BEGIN
    DECLARE total INT DEFAULT 0;
    DECLARE i INT DEFAULT 1;
    repeat 
    set total:=total+i;
    SET i=i+1;
    until i=10 #這裏不需要分號
    END repeat;
    select total;
END $
# 輸出:45
CALL pro_while1(100)$

3、loop

特點:簡單死循環。(相當於while(true))

1)語法

【標簽:】loop
    循環體;
end loop 【標簽】;

2) 示例

#案例:1+2+...100
DELIMITER $
drop procedure if exists `pro_while1` $
CREATE PROCEDURE pro_while1(IN insertCount INT)
BEGIN
    DECLARE total INT DEFAULT 0;
    DECLARE i INT DEFAULT 1;
    a:loop 
    IF i=11 THEN
    LEAVE a;
    END IF;
    set total:=total+i;
    SET i=i+1;
    END loop a;
    select total;
END $

# 輸出:55
CALL pro_while1(100)$

註意: 有while一定要有 end while。有repeat一定要有end repeat。有loop一定要有end loop。




只要自己變優秀了,其他的事情才會跟著好起來(少將9)

Mysql(7)---存儲過程