1. 程式人生 > 實用技巧 >04-儲存過程&函式

04-儲存過程&函式

儲存過程

概述

過程化 SQL 塊主要有 2 種類型,即命名塊和匿名塊。前面介紹的是匿名塊。匿名塊每次執行時都要進行編譯,它不能被儲存到 DB 中,也不能在其他過程化 SQL 塊中呼叫。過程和函式是命名塊,它們被編譯後儲存在 DB 中,稱為“永續性儲存模組”,可以被反覆呼叫,執行速度較快。

儲存過程是由過程化 SQL 語句書寫的過程,這個過程經過編譯和優化後儲存在 DB 伺服器中,因此稱它為“儲存過程”,使用時只要呼叫即可。

定義

CREATE OR REPLACE PROCEDURE <儲存過程名>([引數1, 引數2, ...]) /* 儲存過程首部 */
BEGIN
    /* 儲存過程體, 描述該儲存過程的操作, 是一組 SQL 語句 */
END
  • 儲存過程包括過程首部和過程體
  • 在過程首部,“過程名”是 DB 伺服器合法的物件標識
  • 引數列表包含 3 部分:引數模式 引數名 引數型別
    • 舉例:IN stuName VARCHAR(20)
    • IN 該引數可作為輸入,呼叫方需要傳入值到該引數中
    • OUT 可作為輸出,也就是過程返回值
    • INOUT 既可以作為輸入,又可以作為輸出
  • 過程體 // 如果只有一句話,BEGIN...END 可省
    • 儲存過程體中的每條 SQL 語句的結尾要求必須加 ;
    • 儲存過程的結尾可以使用 DELIMITER 重新設定

操作

  1. 執行儲存過程:CALL <過程名>(實參列表);
  2. 刪除儲存過程:DROP PROCEDURE <過程名>;
  3. 檢視儲存過程:SHOW CREATE PROCEDURE <過程名>;

案例

  1. [無參] 插入到 admin 表中 5 條記錄
  2. [帶 IN 模式] 建立過程實現根據 beauty.name 查詢對應的 boy 資訊
    CREATE PROCEDURE myPro2(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 $
    
  3. [帶 IN 模式] 建立過程實現使用者是否登入成功
    CREATE PROCEDURE myPro3(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 $
    
  4. [帶 OUT 模式] 根據 beauty.name,返回對應的 boy.boyName
  5. [帶 OUT 模式] 根據 beauty.name,返回對應的 boy.id 和 boy.boyName
    CREATE PROCEDURE myPro5(IN bName VARCHAR(20), OUT id VARCHAR(20), OUT name VARCHAR(20))
    BEGIN
        SELECT bo.id, bo.boyName INTO id, name
        FROM boys bo
        INNER JOIN beauty b ON bo.id = b.boyfriend_id
        WHERE b.name = bName;
    END $
    
  6. [帶 INOUT 模式] 傳入 a 和 b 兩個變數,呼叫過程後,a 和 b 的值翻倍
  7. 建立過程實現傳入一個日期,格式化成:xx 年 xx 月 xx 日並返回
    CREATE PROCEDURE myPro7(IN myDate DATETIME, OUT dateStr VARCHAR(30))
    BEGIN
        SELECT DATE_FORMAT(myDate, '%y 年 %m 月 %d 日') INTO strDate;
    END $
    
  8. 建立過程實現傳入 beauty.name,返回:'beauty.name and boys.name' 格式的字串
    CREATE PROCEDURE myPro8(IN beautyName VARCHAR(20), OUT result VARCHAR(20))
    BEGIN
        SELECT CONCAT(beautyName, ' and ', IFNULL(boyName, 'NULL')) INTO result
        FROM boys bo
        RIGHT JOIN beauty b ON bo.id = b.boyfriend_id
        WHERE b.name = beautyName;
    END $
    
  9. 建立過程實現根據傳入的條目數和起始索引,查詢 beauty 表的記錄
    CREATE PROCEDURE myPro8(IN startIndex INT, IN size INT)
    BEGIN
        SELECT * FROM beauty LIMIT startIndex, size;
    END $
    

函式

函式也稱為”自定義函式“,因為是使用者自己使用過程化 SQL 設計定義的。函式和儲存過程類似,都是永續性儲存模組。函式的定義和儲存過程也類似,不同之處是函式必須指定返回的型別。

  • 儲存過程:可以有 0 個返回,也可以有多個返回,適合做批量插入,批量更新
  • 函式:有且只有 1 個返回,適合做處理資料後返回一個結果

定義

CREATE FUNCTION <函式名>([引數名 引數型別 ...]) RETURNS <型別>
BEGIN
    /* 函式體 */
    return 值;
END $

操作

  1. 呼叫函式:SELECT 函式名(引數列表)
  2. 刪除函式:DROP FUNCTION <函式名>
  3. 檢視函式:SHOW CREATE FUNCTION <函式名>

案例

  1. [無參有返回值] 返回 beauty 表記錄數
  2. [有參有返回] 根據員工名,返回他的工資
    CREATE FUNCTION func2(empName VARCHAR(20)) RETURNS DOUBLE
    BEGIN
        SET @sal=0; # 定義使用者變數
        SELECT salary INTO @sal
        FROM employees WHERE last_name = empName;
        RETURN @sal;
    END $
    
  3. 根據部門名返回該部門的平均工資
    CREATE FUNCTION func3(deptName VARCHAR(20)) RETURNS DOUBLE
    BEGIN
        DECLARE avgSal DOUBLE;
        SELECT AVG(salary) INTO avgSal
        FROM employees e RIGHT JOIN departments d
        ON e.department_id = d.department_id
        WHERE d.department_name = deptName;
        RETURN avgSal;
    END $
    
  4. 建立函式,傳入兩個 float,返回二者之和
    CREATE FUNCTION func4(num1 FLOAT, num2 FLOAT) RETURNS FLOAT
    BEGIN
        DECLARE sum FLOAT DEFAULT 0;
        SET sum = num1 + num2;
        RETURN sum;
    END $