1. 程式人生 > 其它 >6、儲存過程與儲存函式

6、儲存過程與儲存函式

儲存過程(Stored Procedure)

多條 SQL 語句處理多個表,儲存過程是一組為了完成特定功能的 SQL 語句集合。

一組經過預先編譯的SQL語句的封裝,呼叫者無需考慮邏輯功能的具體實現過程,它可以被 Java 和 C# 等呼叫。

  使用儲存過程的目的是將常用或複雜的工作預先用 SQL 語句寫好並用一個指定名稱儲存起來,這個過程經編譯和優化後儲存在資料庫伺服器中,因此稱為儲存過程。

優點

  • 簡化操作,提高了sql語句的重用性
  • 減少操作過程中的失誤,提高效率
  • 減少編譯次數,減少和資料庫連線次數
  • 減少網路傳輸量(客戶端不需要把所有的 SQL 語句通過網路發給伺服器)
  • 減少了 SQL 語句暴露在網上的風險,也提高了資料查詢的安全性

建立使用

  • 可以使用 CREATE PROCEDURE 語句建立儲存過程。
  • 語法格式如下:
    DELIMITER 新的結束標記 
    CREATE PROCEDURE 儲存過程名(IN|OUT|INOUT 引數名 引數型別,...)[characteristics ...]
    BEGIN    
        儲存過程體
    END 新的結束標記 
    DELIMITER ;
  • 沒有引數(無引數無返回);僅僅帶 IN 型別(有引數無返回)
  • 僅僅帶 OUT 型別(無引數有返回);既帶 IN 又帶 OUT(有引數有返回)
  • 帶 INOUT(有引數有返回)。IN、OUT、INOUT 都可以在一個儲存過程中帶多個。
  • 儲存過程體中間包含了多條 SQL 語句,每個語句都以(;)號為結束符。DECLARE:用來宣告變數,使用的位置在於 BEGIN…END 語句中間,而且需要在其他語句使用之前進行變數的宣告。
    • 如果僅僅一條SQL 語句,則可以省略 BEGIN 和 END
  • SET:賦值語句,用於對變數進行賦值。
  • SELECT… INTO:把從資料表中查詢的結果存放到變數中,也就是為變數賦值。
  • 需要設定新的結束標記:DELIMITER 新的結束標記
    • 因為MySQL預設的語句結束符號為分號';'。為了避免與儲存過程中SQL語句結束符相沖突,需要使用DELIMITER改變儲存過程的結束符。
    • 儲存過程定義完畢之後再使用“DELIMITER ;”恢復預設結束符。
    • 當使用DELIMITER命令時,應該避免使用反斜槓(‘\’)字元,因為反斜線是MySQL的轉義字元。

示例1:無引數的儲存過程

-- 建立測試表
CREATE TABLE test (tid int);
-- 刪除儲存過程
DROP PROCEDURE p1;
DROP PROCEDURE p2;
DROP PROCEDURE p3;
  • 批量插入
    -- 示例1:無引數的儲存過程.
    -- 建立儲存過程
    CREATE PROCEDURE p1 ()
    BEGIN
        #宣告區域性變數
        DECLARE i INT DEFAULT 1;
        #迴圈
        WHILE i<=10 DO
            #迴圈體 往test表批量插入資料
            INSERT INTO test (tid) VALUES (i);
            #改變迴圈條件
            SET i=i+1;
        END WHILE;
        -- 檢視test表資料
        SELECT*from test;
    END;
    -- 呼叫儲存過程
    CALL p1 ();
  • Loop
    -- 建立儲存過程
    CREATE PROCEDURE p2()
    BEGIN
        #宣告區域性變數
        DECLARE i INT DEFAULT 1;
        #迴圈
        lp : LOOP
            #迴圈體    往test表批量插入資料
            INSERT INTO test (tid) VALUES (i);
            #改變迴圈條件
            SET i=i+1;
            #條件語句判斷迴圈結束條件
            IF i>10 THEN
                LEAVE lp; #退出迴圈
            END IF;
        END LOOP;
        -- 檢視test表資料
        SELECT * from test;
    END;
    -- 呼叫儲存過程
    CALL p2 ();
  • Repeat
    -- 建立儲存過程
    CREATE PROCEDURE p3()
    BEGIN
        #宣告區域性變數
        DECLARE i INT DEFAULT 1;
        #迴圈
        REPEAT
            #迴圈體    往test表批量插入資料
            INSERT INTO test (tid) VALUES ( i);
            #改變迴圈條件
            SET i=i+1;
            #退出迴圈
            UNTIL i>10
        END REPEAT;
        -- 檢視test表資料
        SELECT * from test;
    END;
    -- 呼叫儲存過程
    CALL p3 ();

   

示例2:有in和out引數的儲存過程

  • 練習:根據賬戶編號,返回賬戶餘額,使用者等級。
    • -- 餘額>=2000,顯示使用者等級'磚石會員-- 餘額>=1500,顯示使用者等級'鉑金會員'
    • -- 餘額>=1000,顯示使用者等級'黃金會員-- 餘額>=500,顯示使用者等級'大眾會員'
      -- 建立儲存過程
      DROP PROCEDURE p4;
      create procedure p4(
          IN in_account_id varchar(36),
          OUT out_balance decimal, -- 十進位制
          OUT out_level varchar(20)
      )
      BEGIN 
          SELECT balance,
          CASE
              WHEN balance>=2000 THEN '鑽石會員'
              WHEN balance>=1500 THEN '鉑金會員'
              WHEN balance>=1000 THEN '黃金會員'
              WHEN balance>=500 THEN '大眾會員'
          ELSE '普通會員' 
          END
          AS balance_level INTO out_balance,out_level
          from account where account_id=in_account_id;
      END;
      SET @in_account_id='aec8301d-ab3b-11ec-b6ed-0a0027000018'; -- account 表中有的資料
      CALL p4(@in_account_id,@out_balance,@out_level); -- 呼叫
      SELECT @out_balance,@out_level; -- select輸出出參 

呼叫儲存過程

  • 儲存過程有多種呼叫方法。儲存過程必須使用CALL語句呼叫,並且儲存過程和資料庫相關,如果要執行其他資料庫中的儲存過程,需要指定資料庫名稱。
    CALL 儲存過程名(實參列表) 
    -- 1. 呼叫in模式的引數:
    CALL 儲存過程名(''); 
    -- 2. 呼叫out模式的引數:
    SET @name;
    CALL 儲存過程名(@name);
    SELECT @name; 
    -- 3. 呼叫inout模式的引數:
    SET @name=值;
    CALL 儲存過程名(@name);
    SELECT @name;

刪除

DROP PROCEDURE [IF EXISTS] 儲存過程的名;

儲存函式

建立

DELIMITER 新的結束標記
CREATE FUNCTION 函式名(引數名 引數型別,...)
RETURNS 返回值型別
[characteristics ...]
BEGIN
    函式體 RETURN 語句
END 新的結束標記 
DELIMITER ;
  • 引數列表:指定引數為IN、OUT或INOUT只對PROCEDURE是合法的,FUNCTION中總是預設為IN引數
  • RETURNS type 語句表示函式返回資料的型別;
    • RETURNS子句只能對FUNCTION做指定,對函式而言這是強制的。
    • 它用來指定函式的返回型別,而且函式體必須包含一個RETURN value語句。
  • characteristic 建立函式時指定的對函式的約束。
  • 函式體也可以用BEGIN…END來表示SQL程式碼的開始和結束。如果函式體只有一條語句,也可以省略BEGIN…END。

呼叫儲存函式

SELECT 函式名(實參列表)

刪除

DROP FUNCTION [IF EXISTS] 儲存函式的名;

對比儲存函式和儲存過程

  關鍵字 呼叫語法 返回值 應用場景
儲存過程 PROCEDURE CALL 儲存過程() 理解為有0個或多個 一般用於更新
儲存函式 FUNCTION SELECT 函式() 只能是一個 一般用於查詢結果為一個值並返回時

此外,儲存函式可以放在查詢語句中使用,儲存過程不行。反之,儲存過程的功能更加強大,包括能夠執行對錶的操作(比如建立表,刪除表等)和事務操作,這些功能是儲存函式不具備的。