MySql預存程序與函數

來源:互聯網
上載者:User

標籤:mysql   預存程序   函數   

        林炳文Evankaka原創作品。轉載請註明出處http://blog.csdn.net/evankaka

      摘要:預存程序和函數是在資料庫中定義一些SQL語句的集合,然後直接調用這些預存程序和函數來執行已經定義好的SQL語句。預存程序和函數可以避免開發人員重複的編寫相同的SQL語句。而且,預存程序和函數是在MySQL伺服器中儲存和執行的,可以減少用戶端和伺服器端的資料轉送。

一、預存程序1.1、基本文法

CREATE PROCEDURE sp_name ([proc_parameter[,...]])  [characteristic ...] routine_body

     Sp_name:預存程序的名稱,預設在當前資料庫中建立。這個名稱應當盡量避免與MySQL的內建函數相同的名稱

      Proc_parameter:預存程序的參數列表
      格式[IN|OUT|INOUT]param_name type
      Param_name為參數名,type為參數的資料類型。多個參數彼此間用逗號分隔。輸入參數、輸出參數和輸入/輸出參數,分別用in/out/inout標識。參數的取名不要與數    據表的列名相同。

   Characteristic:預存程序的某些特徵設定,分別介紹
        1 COMMENT’string’:用於對預存程序的描述,其中string為描述內容,comment為關鍵字。
        2 LANGUAGE SQL:指明編寫這個預存程序的語言為SQL語言。這個選項可以不指定。
        3 DETERMINISTIC:表示預存程序對同樣的輸入參數產生相同的結果;NOT DETERMINISTIC,則表示會產生不確定的結果(預設)。

        4 contains sql | no sql | reads sql data | modifies sql data Contains sql表示預存程序包含讀或寫資料的語句(預設)
        No sql表示不包含sql語句
        Reads sql data表示預存程序只包含讀資料的語句
        Modifies sql data 表示預存程序只包含寫資料的語句
        5 sql security:這個特徵用來指定預存程序使用建立該預存程序的使用者(definer)的許可來執行,還是使用調用者(invoker)的許可來執行。預設是definer

    Routine_body:預存程序的主體部分,包含了在程序呼叫的時候必須執行的sql語句。以begin開始,以end結束。如果預存程序體中只有一條sql語句,可以省略begin-end標誌。

1.2、資料準備

CREATE TABLE    t_user    (        USER_ID INT NOT NULL AUTO_INCREMENT,        USER_NAME CHAR(30) NOT NULL,        USER_PASSWORD CHAR(10) NOT NULL,        USER_EMAIL CHAR(30) NOT NULL,        PRIMARY KEY (USER_ID),        INDEX IDX_NAME (USER_NAME)    )    ENGINE=InnoDB DEFAULT CHARSET=utf8;
然後這是插入的一些資料:


1.3 IN、OUT、INOUT參數

(1)、帶IN的預存程序

//建立儲存過程.cmd 中運行CREATE  PROCEDURE  SP_SEARCH(IN p_name CHAR(20))BEGINIF p_name is null or p_name=‘‘ THENSELECT * FROM t_user;ELSESELECT * FROM t_user WHERE USER_NAME LIKE p_name;END IF;END
因為;分會衝突,所以要加delimiter //。將//設定為結束運行符號

如下:


調用:

//調用並輸出結果CALL SP_SEARCH(‘林炳文‘)
結果


(2)、帶OUT的預存程序

//帶OUT返回的CREATE  PROCEDURE  SP_SEARCH2(IN p_name CHAR(20),OUT p_int INT)BEGINIF p_name is null or p_name=‘‘ THENSELECT * FROM t_user;ELSESELECT * FROM t_user WHERE USER_NAME LIKE p_name;END IF;SELECT FOUND_ROWS() INTO p_int;END
調用輸出:統計帶林開頭的人數

//調用並輸出結果CALL SP_SEARCH2(‘林%‘,@p_num);SELECT @p_num;


(3)、帶INOUT的預存程序

//帶INOUT的預存程序CREATE PROCEDURE sp_inout(INOUT p_num INT)BEGINSET p_num=p_num*10;END//調用並輸出結果SET @p_num=2;call sp_inout(@p_num);SELECT @p_num;
輸出結果:

1.4、預存程序體   

       預存程序體中可以使用各種sql語句和過程式語句的組合,來封裝資料庫應用中複雜的商務邏輯和處理規則,以實現資料庫應用的靈活編程。下面主要介紹幾個用於構造預存程序體的常用文法元素。
1、局部變數
在預存程序體中可以聲明局部變數,用來儲存預存程序體中臨時結果。

DECLARE var_name[,…] type [DEFAULT value]Var_name:指定局部變數的名稱Type:用於聲明局部變數的資料類型default子句:用於為局部變數指定一個預設值。若沒有指定,預設為null.
如:
Declare cid int(10);
使用說明:
局部變數只能在預存程序體的begin…end語句塊中聲明。
局部變數必須在預存程序體的開頭處聲明。
局部變數的作用範圍僅限於聲明它的begin..end語句塊,其他語句塊中的語句不可以使用它。
局部變數不同於使用者變數,兩者區別:局部變數聲明時,在其前面沒有使用@符號,並且它只能在begin..end語句塊中使用;而使用者變數在聲明時,會在其名稱前面使用@符號,同時已聲明的使用者變數存在於整個會話之中。
2、set語句

使用set語句為局部變數賦值
Set var_name=exprSet cid=910;
3、select … into 語句
把選定列的值直接儲存到局部變數中,文法格式
Select col_name[,…] into var_name[,…] table_exprCol_name:用於指定列名Var_name:用於指定要賦值的變數名Table_expr:表示select語句中的from字句及後面的文法部分
說明:預存程序體中的select…into語句返回的結果集只能有一行資料。

4、定義處理常式
是事先定義程式執行過程中可能遇到的問題。並且可以在處理常式中定義解決這些問題的辦法。這種方式可以提前預測可能出現的問題,並提出解決方案。

DECLARE handler_type HANDLER FOR condition_value[,…] sp_statementhandler_type:CONTINUE | EXIT | UNDOCondition_value:Sqlwarning | not found | sqlexception
5、流程式控制制語句
(1)條件判斷語句
If語句

If search_condition then statement_list[elseif search_condition then statement_list]…[else statement_list]End if
Search_condition參數:條件判斷語句
Statement_list參數:不同條件的執行語句

多重IF的預存程序執行個體

資料準備

學生表:

CREATE TABLE    t_student    (        STU_ID INT NOT NULL,        STU_NAME CHAR(10) NOT NULL,        STU_CLASS INT NOT NULL,        STU_SEX CHAR(2) NOT NULL,        STU_AGE INT NOT NULL,        PRIMARY KEY (STU_ID)    )    ENGINE=InnoDB DEFAULT CHARSET=utf8;

資料如下:


成績表(STU_ID是學生表是外鍵關係):

CREATE TABLE    t_grade    (        STU_ID INT NOT NULL,        STU_SCORE INT NOT NULL,        FOREIGN KEY (STU_ID) REFERENCES t_student (STU_ID),        INDEX STU_ID (STU_ID)    )    ENGINE=InnoDB DEFAULT CHARSET=utf8;

然後寫一個預存程序:返回各個分數等級的人

//帶多重IF的預存程序CREATE  PROCEDURE SP_SCHOLARSHIP_LEVEL(IN p_level char(1))BEGINIF p_level =‘A‘  THENSELECT * FROM t_grade WHERE STU_SCORE >=90;ELSEIF  p_level =‘B‘  THENSELECT * FROM t_grade WHERE STU_SCORE <90 AND  STU_SCORE>=80;ELSEIF  p_level =‘C‘  THENSELECT * FROM t_grade WHERE STU_SCORE <80 AND  STU_SCORE>=70;ELSEIF  p_level =‘D‘  THENSELECT * FROM t_grade WHERE STU_SCORE <60;ELSESELECT * FROM t_grade;END IF;END

調用過程:
//調用並輸出結果CALL SP_SCHOLARSHIP_LEVEL(‘A‘);

Case 語句
表達形式1
Case case_valueWhen when_value then statement_list[When when_value then statement_list]…[else statement_list]End case
表達形式2
CaseWhen search_condition then statement_listEnd case
使用範例

CREATE  PROCEDURE SP_SCHOLARSHIP_LEVEL3(IN p_level char(1))BEGINDECLARE p_num int DEFAULT  0;CASE p_levelWHEN ‘A‘  THENSET p_num=90;WHEN ‘B‘  THENSET p_num=80;WHEN ‘C‘  THENSET p_num=70;WHEN ‘D‘  THENSET p_num=60;ELSESET p_num=0;END CASE;SELECT * FROM t_grade g, t_student s WHERE g.STU_ID=s.STU_ID AND g.STU_SCORE >= p_num ;END
調用:

//調用並輸出結果CALL SP_SCHOLARSHIP_LEVEL3(‘d‘);



(2)迴圈語句
While語句、repeat語句和loop語句。
While語句

[begin_label:]while search_condition doStatement_listEnd while[end_label]
       判斷條件search_condition是否為真,若為真,則執行statement_list中的語句,然後再進行判斷,如若仍然為真則繼續迴圈,直至條件判斷不為真時迴圈結束。
使用範例

//帶while的預存程序CREATE PROCEDURE sp_cal(IN p_num INT,OUT p_result INT)BEGIN SET p_result=1; WHILE p_num > 1 DO  SET p_result = p_num * p_result;  SET p_num = p_num-1; END WHILE;END//調用並輸出結果CALL sp_cal(5,@result);SELECT @result;
輸出結果:計算5!


Repeat語句文法格式

[begin_label:]repeatStatement_listUntil search_conditionEnd repeat[end_label]
        Repeat語句首先執行statement_list中的語句,然後判斷條件search_condition是否為真,倘若為真,則結束迴圈,若不為真,繼續迴圈。
Repeat先執行後判斷,while先判斷後執行。
使用範例:

//帶repeat的預存程序CREATE PROCEDURE sp_cal2(IN p_num INT,OUT p_result INT)BEGIN  SET p_result=1;  REPEAT    SET p_result = p_num * p_result;    SET p_num = p_num-1;    UNTIL p_num<=1  END REPEAT;END//調用並輸出結果CALL sp_cal2(5,@result);SELECT @result;


1.5、 調用預存程序
Call sp_name([parameter[,…]]);Sp_name被調用預存程序的名稱Parameter:指定調用預存程序所要使用的參數。
1.6、 修改預存程序

Alter procedure proc_name[characteristic…]

只能修改預存程序的特徵,如果要修改預存程序的內容,可以先刪除該預存程序,然後再重新建立
1.7、 刪除預存程序

Drop procedure [if exists] sp_name;
二、函數2.1、 定義

MySQL中,建立儲存函數的基本形式如下:

CREATE FUNCTION sp_name([func_parameter[,...]])RETURNS type[characteristic ...] routine_bodyReturn

子句用於聲明儲存函數傳回值的資料類型。預存程序是使用者定義的一系列sql語句的集合,涉及特定表或其它對象的任務,使用者可以調用預存程序,而函數通常是資料庫已定義的方法,它接收參數並返回某種類型的值並且不涉及特定使用者表。

調用儲存函數

Select sp_name([func_parameter…])Select fn_search(2);
刪除儲存函數drop
修改儲存函數alter 修改儲存函數的某些相關特徵。
2.2、函數使用例子

(比較大小 ,返回大的數)

/**函數使用**/CREATE FUNCTION sp_cal_max(p_num1 INT,p_num2 INT)RETURNS INTBEGINIF p_num1 >= p_num2 THENRETURN p_num1;ELSERETURN p_num2;END IF;END
調用:

SET @p_num1=2;SET @p_num2=34;SELECT sp_cal_max(@p_num1,@p_num2);


2.3、預存程序和函數區別

1)一般來說,預存程序實現的功能要複雜一點,而函數的實現的功能針對性比較強。預存程序,功能強大,可以執行包括修改表等一系列資料庫操作;使用者定義函數不能用於執行一組修改全域資料庫狀態的操作。

2)對於預存程序來說可以返回參數,如記錄集,而函數只能傳回值或者表對象。函數只能返回一個變數;而預存程序可以返回多個。預存程序的參數可以有IN,OUT,INOUT三種類型,而函數只能有IN類~~預存程序聲明時不需要傳回型別,而函式宣告時需要描述傳回型別,且函數體中必須包含一個有效RETURN語句。

3)預存程序,可以使用非確定函數,不允許在使用者定義函數主體中內建非確定函數。

4)預存程序一般是作為一個獨立的部分來執行( EXECUTE 語句執行),而函數可以作為查詢語句的一個部分來調用(SELECT調用),由於函數可以返回一個表對象,因此它可以在查詢語句中位於FROM關鍵字的後面。 SQL語句中不可用預存程序,而可以使用函數。

三、游標(遊標) 3.1 定義

     查詢語句可能查詢出多條記錄,在預存程序和函數中使用游標標來逐條讀取查詢結果集中的記錄。游標的使用包括聲明游標、開啟游標、使用游標和關閉游標。游標必須聲明游標、開啟游標、使用游標和關閉游標。游標必須聲明在處理常式之前,並且聲明在變數和條件之後。

1 聲明游標

Declare cursor_name cursor forselect_statement;Cursor_name:游標名稱Select_statement:select語句的內容Declare cur_employee cursor forselect name,age from employee;

2 開啟游標

Open cursor_nameOpen cur_employee;

3 使用游標

Mysql中使用fetch關鍵字來使用游標,文法形式

Fetch cur_name intovar_name[,var_name…];Cur_name表示游標的名稱Var_name表示將游標中的select語句查詢出來的資訊存入該參數。Var_name必須在聲明游標前就定義好。Fetch cur_employee intoemp_name,emp_age;

4 關閉游標

Close cursor_name;Close cur_employee;

每個游標不再需要時都應該被關閉,使用close語句將會釋放游標所使用的全部資源。在一個游標被關閉後,如果沒有重新被開啟,則不能被使用。對於聲明過的游標,則不需要再次聲明,可直接使用open語句開啟。

3.2、使用範例

(將表test_cur1資料複製到test_cur2)

CREATE TABLE `test_cur1` (    `id` int(11) NOT NULL auto_increment,    `type` char(11) default NULL,    `order1` char(11) default NULL,    PRIMARY KEY  (`id`)  ) INSERT INTO `test_cur1` VALUES (1, ‘145‘, ‘d1‘);  INSERT INTO `test_cur1` VALUES (2, ‘134‘, ‘1d‘);  INSERT INTO `test_cur1` VALUES (3, ‘123‘, ‘1ad‘);  INSERT  INTO `test_cur1` VALUES (4, ‘121‘, ‘1as‘); CREATE TABLE `test_cur2` (    `id` int(11) NOT NULL auto_increment,    `type` char(11) default NULL,    `order1` char(11) default NULL,    PRIMARY KEY  (`id`)  ) 
然後寫游標了:

create procedure get_cur ()BEGIN  DECLARE done INT DEFAULT 0;  DECLARE ID int(11);  DECLARE type char(11);  DECLARE order1 char(11);  DECLARE mycur CURSOR FOR SELECT * FROM test_cur1;//定義游標  DECLARE CONTINUE HANDLER FOR SQLSTATE ‘02000‘ SET done = 1;  //開啟游標  OPEN mycur;  //開始迴圈  REPEAT    FETCH mycur INTO ID,type,order1;//取出游標的內容到臨時變數    IF NOT done THEN      INSERT INTO test_cur2 VALUES (ID,type,order1);//插入到另一張表    END IF;    UNTIL done END REPEAT;//當done=1時結束迴圈  //關閉游標  CLOSE mycur;END

運行:

call get_cur()

來看看兩張表的資料:這是表2


這是表1

說明資料已成功複製過去了

著作權聲明:本文為博主林炳文Evankaka原創文章,未經博主允許不得轉載。

MySql預存程序與函數

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.