1. 程式人生 > >MySQL資料庫儲存過程

MySQL資料庫儲存過程

儲存過程(Stored Procedure)是在大型資料庫系統中,一組為了完成特定功能的SQL 語句集,儲存在資料庫中,經過第一次編譯後再次呼叫不需要再次編譯,使用者通過指定儲存過程的名字並給出引數(如果該儲存過程帶有引數)來執行它。儲存過程是資料庫中的一個重要物件。
——百度百科

儲存過程

如圖所示,在普通模式下獲取資料,使用者需要輸入SQL命令與資料庫進行互動,而儲存過程是編寫好的SQL命令,儲存在資料庫中,使用者操作的時候只需要呼叫儲存過程,而不用重新輸入冗餘繁雜的SQL命令。因此

  • 儲存過程有什麼優點?
    1.儲存過程可以重複使用,大大減小開發人員的負擔;
    2.對於網路上的伺服器,可以大大減小網路流量,因為只需要傳遞儲存過程的名稱即可;
    3,可以防止對錶的直接訪問,只需要賦予使用者儲存過程的訪問許可權。

0 儲存過程相關命令彙總

操作 SQL命令
建立儲存過程 CREATE PROCEDURE 儲存過程名(引數種類1 引數1 資料型別1,[...] BEGIN 具體的procedure(處理) END
檢視資料庫中的儲存過程 SHOW PROCEDURE STATUS\G
檢視具體的儲存過程 SHOW CREATE PROCEDURE 儲存過程名\G
呼叫(執行)儲存過程 CALL 儲存過程名(引數1,...);
刪除儲存過程 DROP PROCEDURE 儲存過程名
變數宣告 DECLARE 變數名 資料型別;
變數賦值 SET 變數名= ;

1 儲存過程

1.1 建立儲存過程 CREATE PROCEDURE

建立儲存過程的命令是:


>CREATE PROCEDURE 儲存過程名(引數種類1 引數1 資料型別1,[...])
 BEGIN
 具體的procedure(處理)
 END
  • 1)儲存過程中具體的處理類容放在BEGINEND 之間;
  • 2)儲存過程需要制定引數,包括種類(IN,OUT,INOUT,分別代表輸入引數,輸出引數和即是輸入也是輸出的引數),引數名和資料型別。【和函式不同,函式指定輸入引數即可】

eg:建立一個對錶customer的姓名(nam)進行模糊檢索,命名為sp_search_customer。

建立儲存過程

對於上圖建立PROCEDURE的幾點說明:
>DELIMITER //表示給變分隔符,預設分隔符是;,否則儲存過程中含有;,MySQL監視器無法分辨。(最後將分隔符改回來)
②儲存過程(BEGINEND 之間)的具體處理內容,主要包括條件、case,迴圈。

分類 SQL命令
簡單條件 IF cond1 THEN
    exp1
ELSEIF cond2 THEN
    exp2
ELSE
    expelse
END IF
case CASE 表示式
    WHEN 值1 THEN …
    WHEN …THEN…
    ELSE …
END CASE
迴圈(後置判斷) REPEAT

UNTIL …END REPEAT
迴圈(前置判斷) WHILE … DO

END WHILE

**1.2 檢視儲存過程** 檢視資料庫中是否存在儲存過程:

>SHOW PROCEDURE STATUS\G

檢視儲存過程的具體資訊:

>SHOW CREATE PROCEDURE 儲存過程名\G

eg:檢視儲存過程sp_search_customer

檢視儲存過程

1.3 執行儲存過程 CALL
呼叫儲存過程使用CALL 儲存過程名命令,具體如下:

CALL 儲存過程名(引數,...)

eg:通過建立好的儲存過程sp_search_cusotmer來執行儲存過程:
檢索‘王’姓顧客:

>CALL sp_search_customer('王%');

檢索所有顧客:

>CALL sp_search_customer('');

呼叫儲存過程

1.4 刪除儲存過程 DROP PROCEDURE
刪除儲存過程使用命令:

DROP PROCEDURE 儲存過程名;

2 儲存過程優化

(1)使用if條件語句建立儲存過程

if條件_儲存過程

可以看到,上述條件語句部分的結構大致都為:

IF... THEN
SELECT...;
ELSEIF ...THEN
SELECT...;
ELSEIF...THEN
SELECT...;
ELSE
SELECT...;

其中的語句具有較高的重複性冗餘性,因此比較繁瑣,如果我們用CASE替代呢?
(2)CASE命令的多重分支

使用CASE來建立多重分支:

CASE_儲存過程

p_dapart放到CASE之後,一個p_dapart取代了多個p_dapart,因此使用CASE程式碼在判斷語句處顯得簡潔一些,如果通過定義變數的形式呢?

(3)定義本地變數

儲存過程中定義的變數,被稱為本地變數,對程式設計語言有所瞭解的知道這是一個區域性變數。資料庫中,
宣告區域性變數的命令:

>DECLARE 變數名 資料型別 [初始值...]

給變數賦值的命令:

>SET 變數名=

,在建立procedure過程中頂一個本地變數tem:

本地變數_儲存過程

可以看到,這種方式大大地簡化了程式碼的冗餘性和重複性。

3 再說儲存過程的輸出引數

在建立儲存過程的時候,如果制定了OUTINOUT,在呼叫儲存過程時請在輸出引數前面加上@,這樣結果將儲存到“@變數名“中。

eg:建立一個計算階乘的儲存過程:

儲存過程輸出引數

最終的結果將儲存到“@res“之中,如上圖所示。

  • 請注意,用WHILE迴圈建立的計算階乘的儲存過程,!5=120,!0=1,結果是正確的。先記住這句話,接下來看下用REPEAT建立同樣的階乘計算的儲存過程。

4 再說WHILE 和 REPEAT迴圈

我們使用repeat建立一個計算階乘的儲存過程:

REPEAT_儲存過程

接下來看下同樣計算!5!0結果如何?

repeat_儲存過程

可以看到!5=120的結果正確,但是!0得到的結果為0,不為1。這是什麼原因呢?
問題出在WHILE是前置判斷,是先驗的,先驗證WHILE後面的條件是否成立,為TRUE則繼續執行,若FALSE則結束迴圈;
而REPEAT是後置判斷,是後驗的,不管三七二十一先執行語句,然後驗證UNTIL後面的條件語句是否成立,不成立則結束。因此REPEAT迴圈執行了一次presult=presultpnumpresult=10
因此:

  • WHILE迴圈是前置判斷,先驗的迴圈
  • REPEAT迴圈是後置判斷,後驗的迴圈