首頁 > 軟體

MySQL中儲存過程的詳細詳解

2022-06-26 18:00:40

概述

由MySQL5.0 版本開始支援儲存過程。

如果在實現使用者的某些需求時,需要編寫一組複雜的SQL語句才能實現的時候,那麼我們就可以將這組複雜的SQL語句集提前編寫在資料庫中,由JDBC呼叫來執行這組SQL語句。把編寫在資料庫中的SQL語句集稱為儲存過程。

儲存過程:(PROCEDURE)是事先經過編譯並儲存在資料庫中的一段SQL語句的集合。呼叫儲存過程可以簡化應用開發人員的很多工作,減少資料在資料庫和應用伺服器之間的傳輸,對於提高資料處理的效率是很有好處的。

就是資料庫 SQL 語言層面的程式碼封裝與重用。

儲存過程就類似於Java中的方法,需要先定義,使用時需要呼叫。儲存過程可以定義引數,引數分為IN、OUT、INOUT型別三種型別。

  • IN型別的參數列示接受呼叫者傳入的資料;
  • OUT型別的參數列示向呼叫者返回資料;
  • INOUT型別的引數即可以接受呼叫者傳入的引數,也可以向呼叫者返回資料。

優點

  1. 儲存過程是通過處理封裝在容易使用的單元中,簡化了複雜的操作。
  2. 簡化對變動的管理。如果表名、列名、或業務邏輯有了變化。只需要更改儲存過程的程式碼。使用它的人不用更改自己的程式碼。
  3. 通常儲存過程都是有助於提高應用程式的效能。當建立的儲存過程被編譯之後,就儲存在資料庫中。
    但是,MySQL實現的儲存過程略有所不同。
    MySQL儲存過程是按需編譯。在編譯儲存過程之後,MySQL將其放入快取中。
    MySQL為每個連線維護自己的儲存過程快取記憶體。如果應用程式在單個連線中多次使用儲存過程,則使用編譯版本,否則儲存過程的工作方式類似於查詢。
  4. 儲存過程有助於減少應用程式和資料庫伺服器之間的流量。
    因為應運程式不必傳送多個冗長的SQL語句,只用傳送儲存過程中的名稱和引數即可。
  5. 儲存過程度任何應用程式都是可重用的和透明的。儲存過程將資料庫介面暴露給所有的應用程式,以方便開發人員不必開發儲存過程中已支援的功能。
  6. 儲存的程式是安全的。資料庫管理員是可以向存取資料庫中儲存過程的應用程式授予適當的許可權,而不是向基礎資料庫表提供任何許可權。

缺點

  1. 如果使用大量的儲存過程,那麼使用這些儲存過程的每個連線的記憶體使用量將大大增加。
    此外,如果在儲存過程中過度使用大量的邏輯操作,那麼CPU的使用率也在增加,因為MySQL資料庫最初的設計就側重於高效的查詢,而不是邏輯運算。
  2. 儲存過程的構造使得開發具有了複雜的業務邏輯的儲存過程變得困難。
  3. 很難偵錯儲存過程。只有少數資料庫管理系統允許偵錯儲存過程。不幸的是,MySQL不提供偵錯儲存過程的功能。
  4. 開發和維護儲存過程都不容易。
    開發和維護儲存過程通常需要一個不是所有應用程式開發人員擁有的專業技能。這可能導致應用程式開發和維護階段的問題。
  5. 對資料庫依賴程度較高,移值性差。

MySQL儲存過程的定義

儲存過程的基本語句格式

DELIMITER $$

CREATE
    /*[DEFINER = { user | CURRENT_USER }]*/
    PROCEDURE 資料庫名.儲存過程名([in變數名 型別,out 引數 2,...])
    /*LANGUAGE SQL
    | [NOT] DETERMINISTIC
    | { CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA }
    | SQL SECURITY { DEFINER | INVOKER }
    | COMMENT 'string'*/
	BEGIN
		[DECLARE 變數名 型別 [DEFAULT 值];]
		儲存過程的語句塊;
	END$$

DELIMITER ;

● 儲存過程中的引數分別是 in,out,inout三種型別;

  1. in代表輸入引數(預設情況下為in引數),表示該引數的值必須由呼叫程式指定。
  2. ou代表輸出引數,表示該引數的值經儲存過程計算後,將out引數的計算結果返回給呼叫程式。
  3. inout代表即時輸入引數,又是輸出引數,表示該引數的值即可有呼叫程式制定,又可以將inout引數的計算結果返回給呼叫程式。

● 儲存過程中的語句必須包含在BEGIN和END之間。

● DECLARE中用來宣告變數,變數預設賦值使用的DEFAULT,語句塊中改變變數值,使用SET 變數=值;

儲存過程的使用

定義一個儲存過程

DELIMITER $$

CREATE
    PROCEDURE `demo`.`demo1`()
	-- 儲存過程體
	BEGIN
		-- DECLARE宣告 用來宣告變數的
		DECLARE de_name VARCHAR(10) DEFAULT '';
		
		SET de_name = "jim";
		
		-- 測試輸出語句(不同的資料庫,測試語句都不太一樣。
		SELECT de_name;
	END$$

DELIMITER ;

呼叫儲存過程

CALL demo1();

定義一個有引數的儲存過程

先定義一個student資料庫表:

現在要查詢這個student表中的sex為男的有多少個人。

DELIMITER $$

CREATE
    PROCEDURE `demo`.`demo2`(IN s_sex CHAR(1),OUT s_count INT)
	-- 儲存過程體
	BEGIN
		-- 把SQL中查詢的結果通過INTO賦給變數
		SELECT COUNT(*) INTO s_count FROM student WHERE sex= s_sex;
		SELECT s_count;
		
	END$$
DELIMITER ;

呼叫這個儲存過程

-- @s_count表示測試出輸出的引數
CALL demo2 ('男',@s_count);

定義一個流程控制語句 IF ELSE

IF 語句包含多個條件判斷,根據結果為 TRUE、FALSE執行語句,與程式語言中的 if、else if、else 語法類似。

DELIMITER $$
CREATE
    PROCEDURE `demo`.`demo3`(IN `day` INT)
	-- 儲存過程體
	BEGIN
		IF `day` = 0 THEN
		SELECT '星期天';
		ELSEIF `day` = 1 THEN
		SELECT '星期一';
		ELSEIF `day` = 2 THEN
		SELECT '星期二';
		ELSE
		SELECT '無效日期';
		END IF;
		
	END$$
DELIMITER ;

呼叫這個儲存過程

CALL demo3(2);

定義一個條件控制語句 CASE

case是另一個條件判斷的語句,類似於程式語言中的 choose、when語法。MySQL 中的 case語句有兩種語法格式。

第一種

DELIMITER $$
CREATE 
    PROCEDURE demo4(IN num INT)
	BEGIN
		CASE -- 條件開始
	
		WHEN num<0 THEN 
			SELECT '負數';
		WHEN num>0 THEN 
			SELECT '正數';
		ELSE 
		SELECT '不是正數也不是負數';
	
		END CASE; -- 條件結束
	END$$
DELIMITER;

呼叫這個儲存過程

CALL demo4(1);

2.第二種

DELIMITER $$
CREATE 
    PROCEDURE demo5(IN num INT)
	BEGIN
		CASE num  -- 條件開始
		WHEN 1 THEN 
			SELECT '輸入為1';
		WHEN 0 THEN 
			SELECT '輸入為0';
		ELSE 
		SELECT '不是1也不是0';
		END CASE; -- 條件結束
	END$$
DELIMITER;

呼叫此函數

CALL demo5(0);

定義一個迴圈語句 WHILE

DELIMITER $$
CREATE 
    PROCEDURE demo6(IN num INT,OUT SUM INT)
	BEGIN
	     SET SUM = 0;
	     WHILE num<10 DO -- 迴圈開始
	         SET num = num+1;
	         SET SUM = SUM+num;
	         END WHILE; -- 迴圈結束
	END$$
DELIMITER;

呼叫此函數

-- 呼叫函數
CALL demo6(0,@sum);

-- 查詢函數
SELECT @sum;

定義一個迴圈語句 REPEAT UNTLL

REPEATE…UNTLL 語句的用法和 Java中的 do…while 語句類似,都是先執行迴圈操作,再判斷條件,區別是REPEATE 表示式值為 false時才執行迴圈操作,直到表示式值為 true停止。

-- 建立過程
DELIMITER $$
CREATE 
    PROCEDURE demo7(IN num INT,OUT SUM INT)
	BEGIN
	     SET SUM = 0;
	     REPEAT-- 迴圈開始
		SET num = num+1;
		SET SUM = SUM+num ;
		UNTIL num>=10
		END REPEAT; -- 迴圈結束
	END$$
DELIMITER;

呼叫此函數

CALL demo7(9,@sum);

SELECT @sum;

定義一個迴圈語句 LOOP

迴圈語句,用來重複執行某些語句。

執行過程中可使用 LEAVE語句或者ITEREATE來跳出迴圈,也可以巢狀IF等判斷語句。

LEAVE 語句效果對於Java中的break,用來終止迴圈;

ITERATE語句效果相當於Java中的continue,用來跳過此次迴圈。進入下一次迴圈。且ITERATE之下的語句將不在進行。

DELIMITER $$
CREATE 
    PROCEDURE demo8(IN num INT,OUT SUM INT)
	BEGIN
	     SET SUM = 0;
	     demo_sum:LOOP-- 迴圈開始
		SET num = num+1;
		IF num > 10 THEN
		    LEAVE demo_sum; -- 結束此次迴圈
		ELSEIF num < 9 THEN
		    ITERATE demo_sum; -- 跳過此次迴圈
		END IF;
		
		SET SUM = SUM+num;
		END LOOP demo_sum; -- 迴圈結束
	END$$
DELIMITER;

呼叫此函數

CALL demo8(0,@sum);

SELECT @sum;

使用儲存過程插入資訊

DELIMITER $$
CREATE 
    PROCEDURE demo9(IN s_student VARCHAR(10),IN s_sex CHAR(1),OUT s_result VARCHAR(20))
	BEGIN
	   -- 宣告一個變數 用來決定這個名字是否已經存在
	   DECLARE s_count INT DEFAULT 0;
	   -- 驗證這麼名字是否已經存在
	   SELECT COUNT(*) INTO s_count FROM student WHERE `name` = s_student;	
	   IF s_count = 0 THEN
	        INSERT INTO student (`name`, sex) VALUES(s_student, s_sex);
		SET s_result = '資料新增成功';
	   ELSE
                SET s_result = '名字已存在,不能新增';
                SELECT s_result;
	   END IF;
	END$$
DELIMITER;

呼叫此函數

CALL demo9("Jim","女",@s_result);

再次呼叫次函數

CALL demo9("Jim","女",@s_result)

儲存過程的管理

顯示儲存過程

SHOW PROCEDURE STATUS

顯示特定資料庫的儲存過程

SHOW PROCEDURE STATUS WHERE db = 'db名字' AND NAME = 'name名字';

顯示特定模式的儲存過程

SHOW PROCEDURE STATUS WHERE NAME LIKE '%mo%';

顯示儲存過程的原始碼

SHOW CREATE PROCEDURE 儲存過程名;

刪除儲存過程

DROP PROCEDURE 儲存過程名;

後端呼叫儲存過程的實現

在mybatis當中,呼叫儲存過程

<parameterMap type="savemap" id=「usermap"> 
	<parameter property="name" jdbcType="VARCHAR" mode="IN"/>
	<parameter property="sex" jdbcType="CHAR" mode="IN"/>
	<parameter property="result" jdbcType="VARCHAR" mode="OUT"/>
</parameterMap>

<insert id="saveUserDemo" parameterMap="savemap" statementType="CALLABLE"> 
{call saveuser(?, ?, ?)} 
</insert >

呼叫資料庫管理

HashMap<String, Object> map = new HashMap<String, Object>(); 
	map.put("name", "Jim"); 
	map.put("sex","男");
	userDao.saveUserDemo(map); 
	map.get(「result」);//獲得輸出引數

通過這樣就可以呼叫資料庫中的儲存過程的結果。

總結

到此這篇關於MySQL中儲存過程的文章就介紹到這了,更多相關MySQL儲存過程內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com