MySql存儲過程語法及事例

摘自 :http://www.cnblogs.com/lp-zy/p/4360398.html

在MySQL 5中,終於引入了存儲過程這一新特性,這將大大增強MYSQL的數據庫處理能力。在本文中將指導讀者快速掌握MySQL 5的存儲過程的基本知識,帶領用戶入門。

  存儲過程介紹

  存儲過程是一組爲了完成特定功能的SQL語句集,經編譯後存儲在數據庫中。用戶通過指定存儲過程的名字並給出參數(如果該存儲過程帶有參數)來執行它。存儲過程可由應用程序通過一個調用來執行,而且允許用戶聲明變量 。同時,存儲過程可以接收和輸出參數、返回執行存儲過程的狀態值,也可以嵌套調用。

  存儲過程的優點

  作爲存儲過程,有以下這些優點:

  (1) 減少網絡通信量。調用一個行數不多的存儲過程與直接調用SQL語句的網絡通信量可能不會有很大的差別,可是如果存儲過程包含上百行SQL語句,那麼其性能絕對比一條一條的調用SQL語句要高得多。

  (2) 執行速度更快。存儲過程創建的時候,數據庫已經對其進行了一次解析和優化。其次,存儲過程一旦執行,在內存中就會保留一份這個存儲過程,這樣下次再執行同樣的存儲過程時,可以從內存中直接中讀取。

  (3) 更強的安全性。存儲過程是通過向用戶授予權限(而不是基於表),它們可以提供對特定數據的訪問,提高代碼安全,比如防止 SQL注入。

  (4) 業務邏輯可以封裝存儲過程中,這樣不僅容易維護,而且執行效率也高

  當然存儲過程也有一些缺點,比如:

  (1) 可移植性方面:當從一種數據庫遷移到另外一種數據庫時,不少的存儲過程的編寫要進行部分修改。

  (2) 存儲過程需要花費一定的學習時間去學習,比如學習其語法等。

  在MySQL中,推薦使用MySQL Query Browswer(http://dev.mysql.com/doc/query-browser/en/)這個工具去進行存儲過程的開發和管理。下面分步驟來學習MYSQL中的存儲過程。

  1、定義存儲過程的結束符

  在存儲過程中,通常要輸入很多SQL語句,而SQL語句中每個語句以分號來結束,因此要告訴存儲過程,什麼位置是意味着整個存儲過程結束,所以我們在編寫存儲過程前,先定義分隔符,我們這裏定義//爲分隔符,我們使用DELIMITER //這樣的語法,就可以定義結束符了,當然你可以自己定義其他喜歡的符號。

  2、如何創建存儲過程

  下面先看下一個簡單的例子,代碼如下:

複製代碼
DELIMITER //
CREATEPROCEDURE `p2` ()
LANGUAGE SQL
DETERMINISTIC
SQL SECURITY DEFINER
COMMENT 'A procedure'
BEGIN
SELECT'Hello World !';
END//
複製代碼

  下面講解下存儲過程的組成部分:

  1) 首先在定義好終結符後,使用CREATE PROCEDURE+存儲過程名的方法創建存儲過程,LANGUAGE選項指定了使用的語言,這裏默認是使用SQL。

  2) DETERMINISTIC關鍵詞的作用是,當確定每次的存儲過程的輸入和輸出都是相同的內容時,可以使用該關鍵詞,否則默認爲NOT DETERMINISTIC。

  3) SQL SECURITY關鍵詞,是表示調用時檢查用戶的權限。當值爲INVOKER時,表示是用戶調用該存儲過程時檢查,默認爲DEFINER,即創建存儲過程時檢查。

  4) COMMENT部分是存儲過程的註釋說明部分。

  5) 在BEGIN END部分中,是存儲過程的主體部分。

  3、調用存儲過程的方法

  調用存儲過程的方法很簡單,只需要使用call命令即可,後面跟要調用存儲過程的名稱及輸入的變量列表,比如:

CALL stored_procedure_name (param1, param2, ....)
CALL procedure1(10 , 'string parameter' , @parameter_var);

  4、修改和刪除存儲過程

  可以用ALTER的語法去修改存儲過程的主要特徵和參數,要修改其存儲過程的主體部分的話,必須要先刪除然後再重建。比如下面修改存儲過程num_from_employee的定義。將讀寫權限改爲MODIFIES SQL DATA,並指明調用者可以執行。代碼執行如下:

ALTER PROCEDURE num_from_employee
MODIFIES SQL DATA SQL SECURITY INVOKER ;

  而刪除存儲過程的語法爲使用DROP關鍵詞即可。如下

DROP PROCEDURE IF EXISTS p2;

  5、存儲過程的參數

  下面來學習下存儲過程中的參數,先看下存儲過程中的參數形式,如下:

  CREATE PROCEDURE proc1 () 這個存儲過程中是空的參數列表

  CREATE PROCEDURE proc1 (IN varname DATA-TYPE) 這個存儲過程中有一個輸出參數,名稱爲varname,後面是跟數據類型DATA-TYPE,IN參數是默認的,因此可以省略不寫

  CREATE PROCEDURE proc1 (OUT varname DATA-TYPE) 這個存儲過程中varname爲輸出參數

  CREATE PROCEDURE proc1 (INOUT varname DATA-TYPE) 這個存儲過程中,varname既是輸入參數也是輸出參數

  下面具體看個例子,首先是IN輸入參數的例子,如下:

DELIMITER //
CREATE PROCEDURE `proc_IN` (IN var1 INT)
BEGIN
    SELECT var1 + 2 AS result;
END//

  輸出OUT參數例子如下:

DELIMITER //
CREATE PROCEDURE `proc_OUT` (OUT var1 VARCHAR(100))
BEGIN
  SET var1 = 'This is a test';
END //

  IN-OUT的例子:

DELIMITER //
CREATE PROCEDURE `proc_INOUT` (OUT var1 INT)
BEGIN
  SET var1 = var1 * 2;
END //

  6、如何定義變量

  下面講解下MySQL 5存儲過程中,如何定義變量。必須顯式地在存儲過程的一開始聲明變量,並指出它們的數據類型,一但聲明瞭變量後,就可以在存儲過程中使用,定義變量的語法如下:

  DECLARE varname DATA-TYPE DEFAULT defaultvalue

  舉例說明:

DECLARE a, b INT DEFAULT 5;
DECLARE str VARCHAR(50);
DECLARE today TIMESTAMP DEFAULT CURRENT_DATE;
DECLARE v1, v2, v3 TINYINT;

  一旦定義好變量,就可以在存儲過程中對其進行賦初值,並進行各類相關的操作,比如:

複製代碼
DELIMITER //
CREATE PROCEDURE `var_proc` (IN paramstr VARCHAR(20))
BEGIN
  DECLARE a, b INT DEFAULT 5;
  DECLARE str VARCHAR(50);
  DECLARE today TIMESTAMP DEFAULT CURRENT_DATE;
  DECLARE v1, v2, v3 TINYINT;
  INSERT INTO table1 VALUES (a);
  SET str = 'I am a string';
  SELECT CONCAT(str,paramstr), today FROM table2 WHERE b>=5;
END //
複製代碼

  7、MYSQL存儲過程的語法結構

  MYSQL存儲過程中支持IF,CASE,ITERATE,LEAVE LOOP,WHILE和REPEAT等語法結構和語句,在本文中,着重介紹IF,CASE和WHILE語法,因爲它們使用的最爲廣泛。

  IF 語句

  if語句使用的是if…then end if的語法結構,例子如下:

複製代碼
DELIMITER //
CREATE PROCEDURE `proc_IF` (IN param1 INT)
BEGIN
  DECLARE variable1 INT;
  SET variable1 = param1 + 1;
  IF variable1 = 0 THEN
      SELECT variable1;
  END IF;
  IF param1 = 0 THEN
      SELECT 'Parameter value = 0';
  ELSE
      SELECT 'Parameter value <= 0';
  END IF;
END //
複製代碼

  CASE語句

  當有很多IF語句時,就應該考慮使用CASE語句了,它是多分支選擇語句,有兩種寫法:

  第一種寫法:

複製代碼
DELIMITER //
CREATE PROCEDURE `proc_CASE` (IN param1 INT)
BEGIN
  DECLARE variable1 INT;
  SET variable1 = param1 + 1;
  CASE variable1
  WHEN 0 THEN
      INSERT INTO table1 VALUES (param1);
  WHEN 1 THEN
      INSERT INTO table1 VALUES (variable1);
  ELSE
      INSERT INTO table1 VALUES (99);
  END CASE;
END //
複製代碼

  另外一種寫法:

複製代碼
DELIMITER //
CREATE PROCEDURE `proc_CASE` (IN param1 INT)
BEGIN
  DECLARE variable1 INT;
  SET variable1 = param1 + 1;
  CASE
  WHEN variable1 = 0 THEN
      INSERT INTO table1 VALUES (param1);
  WHEN variable1 = 1 THEN
      INSERT INTO table1 VALUES (variable1);
  ELSE
      INSERT INTO table1 VALUES (99);
  END CASE;
END //
複製代碼

  WHILE語句

  WHILE語句跟普通編程語言中的while語句差不多,例子如下:

複製代碼
DELIMITER //
CREATE PROCEDURE `proc_WHILE` (IN param1 INT)
BEGIN
  DECLARE variable1, variable2 INT;
  SET variable1 = 0;
  WHILE variable1
      INSERT INTO table1 VALUES (param1);
      SELECT COUNT(*) INTO variable2 FROM table1;
      SET variable1 = variable1 + 1;
  END WHILE;
END //
複製代碼

  8、MYSQL存儲過程中的遊標

  MySQL中的遊標是一個十分重要的概念。遊標提供了一種對從表中檢索出的數據進行操作的靈活手段,就本質而言,遊標實際上是一種能從包括多條數據記錄的結果集中每次提取一條記錄的機制。MySQL中的遊標的語法如下:

DECLARE cursor-name CURSOR FOR SELECT ...; /* 聲明一個遊標,名稱爲cursor-name,並用CURSOR FOR SELECT*/
DECLARE CONTINUE HANDLER FOR NOT FOUND /*指定當遍歷完結果集後,遊標如何繼續處理*/
OPEN cursor-name; /*打開遊標 */
FETCH cursor-name INTO variable [, variable]; /* 將變量賦值給遊標*/
CLOSE cursor-name; /*使用後關閉遊標*/

 一個具體的例子如下:

複製代碼
DELIMITER //
CREATE PROCEDURE `proc_CURSOR` (OUT param1 INT)
BEGIN
  DECLARE a, b, c INT;
  DECLARE cur1 CURSOR FOR SELECT col1 FROM table1;
  DECLARE CONTINUE HANDLER FOR NOT FOUND SET b = 1;
  OPEN cur1;
  SET b = 0;
  SET c = 0;
  WHILE b = 0 DO
      FETCH cur1 INTO a;
      IF b = 0 THEN
          SET c = c + a;
      END IF;
  END WHILE;
  CLOSE cur1;
  SET param1 = c;
END //
複製代碼

  其中,DECLARE cur1 CURSOR FOR SELECT col1 FROM table1;

  表示將從table1表中選取col1列的內容放到遊標curl中,即每次遊標遍歷的結果都放在curl中,要注意遊標只能向前遍歷,而不能向後,並且注意,遊標不能更新,最後關閉遊標。



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章