MySQL4:存儲過程和函數

什麼是存儲過程數據庫

簡單說,存儲過程就是一條或多條SQL語句的集合,可視爲批文件,可是起做用不只限於批處理。本文主要講解如何建立存儲過程和存儲函數以及變量的使用,如何調用、查看、修改、刪除存儲過程和存儲函數等。使用的數據庫和表仍是以前寫JDBC用的數據庫和表:瀏覽器

create database school;

use school;

create table student
(
    studentId            int                 primary key    auto_increment    not null,
    studentName        varchar(10)                                                            not null,
    studentAge        int,
    studentPhone    varchar(15)
)

insert into student values(null,'Betty', '20', '00000000');
insert into student values(null,'Jerry', '18', '11111111');
insert into student values(null,'Betty', '21', '22222222');
insert into student values(null,'Steve', '27', '33333333');
insert into student values(null,'James', '22', '44444444');
commit;

存儲程序能夠分爲存儲過程和函數,MySQL中建立存儲過程和函數的語句分別是:CREATE PROCEDURE和CREATE FUNCTION。使用CALL語句來調用存儲過程,只能用輸出變量返回值。函數能夠從語句外調用(即經過引用函數名),也能返回標量值。存儲過程也能夠調用其餘存儲過程。函數

 

建立存儲過程oop

建立存儲過程,須要使用CREATE PROCEDURE語句,語句基本格式以下:spa

CREATE PROCEDURE sp_name([proc_parameter]) 
[characteristics ...] routine_body

解釋一下:code

一、CREATE PROCEDURE爲建立存儲過程的關鍵字blog

二、sp_name爲存儲過程的名字ip

三、proc_parameter爲指定存儲過程的參數列表,列表形式爲[IN|OUT|INOUT] param_name type。其中,IN表示輸入參數,OUT表示輸出參數,INOUT表示既能夠輸入也能夠輸出,param_name表示參數名稱,type表示參數類型,該類型能夠是MySQL數據庫中的任意類型開發

四、characteristics指定存儲過程的特性rem

五、routime_body是SQL代碼的內容,能夠用BEGIN...END來表示SQL代碼的開始和結束

編寫存儲過程不是簡單的事情,可能存儲過程當中須要複雜的SQL語句,而且要有建立存儲過程的權限;可是使用存儲過程將簡化操做,減小冗餘的操做步驟,同時還能夠減小操做過程當中的事物,提升效率,所以存儲過程是很是有用的。下面看兩個存儲過程,一個查詢student表中的全部字段,一個根據student表的Age字段算一個Age的平均值:

CREATE PROCEDURE proc ()
BEGIN
    SELECT * FROM student;
END;
CREATE PROCEDURE AvgStudentAge()
BEGIN
    SELECT AVG(studentAge) AS avgAge FROM student;
END;

上面都是不帶參數的存儲過程,下面看一個帶參數的存儲過程:

DELIMITER //
CREATE PROCEDURE CountStudent(IN sName VARCHAR(10), OUT num INT)
BEGIN
    SELECT COUNT(*) INTO num FROM student WHERE studentName = sName;
END //

上述代碼的做用是建立一個獲取student表記錄條數的存儲過程,名稱爲CountStudent,根據傳入的學生姓名COUNT(*)後把結果放入參數num中。

注意另一個細節,上述代碼第一行使用了"DELIMITER //",這句語句的做用是把MySQL的結束符設置爲"//",由於MySQL默認的語句結束符號爲分號";",爲了不與存儲過程當中SQL語句結束符相沖突,須要使用DELIMITER改變存儲過程的結束符,並以"END //"結束存儲過程。存過程定義完畢以後再使用"DELIMITER ;"恢復默認結束符。DELIMITER也能夠指定其餘符號做爲結束符。

 

建立存儲函數

建立存儲函數須要使用CREATE FUNCATION語句,其基本語法以下:

CREATE FUNCTION func_name([func_parameter]) RETURNS type
[characteristic ...] routine_body

解釋一下:

一、CREATE_FUNCTION爲用來建立存儲函數的關鍵字

二、func_name表示存儲函數的名稱

三、func_parameter爲存儲過程的參數列表,參數列表形式爲[IN|OUT|INOUT] param_name type,和存儲過程同樣

四、RETURNS type表示函數返回數據的類型

五、characteristic表示存儲函數的特性,和存儲過程同樣

舉個例子:

CREATE FUNCTION NameByZip() RETURNS CHAR(50)
RETURN (select studentPhone from student where studentName = 'JAMES');

提兩點:

一、若是在存儲函數中的RETURN語句返回一個類型不一樣於函數的RETURNS自居指定的類型的值,返回值將被強制爲恰當的類型

二、指定參數爲IN、OUT或INOUT只對PROCEDURE是合法的(FUNCTION中老是默認爲IN參數)。RETURNS子句只能對FUNCTION作指定,對於函數而言這是強制性的,它用來指定函數的返回類型,並且函數體必須包含一個RETURN value語句

 

變量的使用

變量能夠在子程序中聲明並使用,這些變量的做用範圍是在BEGIN...END程序中,在存儲過程當中可使用DECLARE語句定義變量,語法以下:

DECLARE var_name[,varame]... date_type [DEFAULT value]

解釋一下:

一、var_name爲局部變量的名稱

二、DEFAULT value子句給變量提供一個默認值,值除了能夠被聲明爲一個常數以外,還能夠被指定爲一個表達式。若是沒有DEFAULT子句,那麼初始值爲NULL

定義變量後,爲變量賦值能夠改變變量的默認值,MySQL使用SET爲變量賦值:

SET var_name=expr[, var_name=expr] ...;

舉個例子:

DECLARE var1 INT DEFAULT 100;
DECLARE var2, var3, var4 INT;
SET var2 = 10, var3 = 20;
SET var4 = var2 + var3;

固然,咱們使用SELECT語句也能夠給變量賦值:

DECLARE t_studentName CHAR(20);
DECLARE t_studentAge INT;
SELECT studentName, studentId INTO t_studentName, t_studentAge FROM student where studentName = 'Bruce';DECLARE t_studentName CHAR(20);
DECLARE t_studentAge INT;

 

遊標的使用

查詢語句可能返回多條記錄,若是數據量很是大,須要在存儲過程和存儲函數中使用遊標來逐條讀取查詢結果集中的記錄。應用程序能夠根據須要滾動或瀏覽器中的程序。

遊標必須在處理程序以前被聲明,而且變量和條件還必須在聲明遊標或處理程序以前被聲明。MySQL中聲明遊標的方法爲:

DECLARE cursor_name CURSOR FOR select_statement

解釋一下:

一、cursor_name表示遊標的名稱

二、select_statement表示SELECT語句返回的內容,返回一個用於建立遊標的結果集

定義了遊標,就要打開遊標,打開遊標的方法爲:

OPEN cursor_name{遊標名稱}

再就是使用遊標了,使用遊標的方法爲:

FETCH cursor_name INTO var_name [, var_name] ... {參數名稱}

最後遊標使用完了,要關閉:

CLOSE cursor_name{遊標名稱}

舉個例子:

DECLARE t_studentName CHAR(20);
DECLARE t_studentAge INT;
DECLARE cur_student CURSOR FOR SELECT studentName, studentId FROM student where studentName = 'Bruce';
OPEN cur_student;
FETCH cur_student INTO t_studentName, t_studentAge;
...
CLOSE cur_student;

studentName爲Bruce的在數據裏面不止一條記錄,建立遊標以後就從student表中查出了studentName和studentId的值。OPEN這個遊標,經過FETCH以後遍歷每一組studentName和studentAge,並放入申明的變量t_studentName和t_studentAge中,以後想怎麼用這兩個字段怎麼用這兩個字段了。注意,遊標用完關閉掉。

 

IF、CASE、LOOP、LEAVE、ITERATE、REPEAT

這六個比較簡單,放在一塊兒講了,簡單說下用法,除了第一個IF寫個例子之外,別的就不寫例子了,能夠本身嘗試下。

一、IF

IF語句包含多個判斷條件,根據判斷的結果爲TRUE或FALSE執行相應的語句,其格式爲:

IF expr_condition THEN statement_list
    [ELSEIF expr_condition THEN statement_list]
    [ELSE statement_list]    
END IF

好比:

IF t_studentName IS NULL
    THEN SELECT studentName INTO t_studentName FROM student where studentName = 'Bruce';
    ELSE UPDATE studentName set student = NULL where studentName = 'Bruce';
END IF;

二、CASE

case是另一個進行條件判斷的語句,該語句有兩種格式,第一種格式以下:

CASE case_expr
    WHEN when_value THEN statement_list
    [WHEN when_value THEN statement_list] ...
    [ELSE statement_list]
END CASE

其中,case_expr參數表示判斷的表達式,決定了哪個WHEN自居會被執行;when_value表示表達式可能的值,若是某個when_value表達式與case_expr表達式結果相同,則執行對應THEN關鍵字後的statement_list中的語句;statement_list參數表示不一樣when_value值的執行語句。

CASE語句的第二種格式爲:

CASE
    WHEN expr_condition THEN statement_list
    [WHEN expr_condition THEN statement_list] ...
    [ElSE statement_list]
END CASE

只是寫法稍微變了一下,參數仍是第一種寫法的意思

三、LOOP

LOOP循環用來重複執行某些語句,與IF和CASE相比,LOOP只是建立一個循環操做的過程,並不進行條件判斷。LOOP內的語句一直被重複執行直到循環被退出,跳出循環過程,使用LEAVE子句。LOOP語句j的基本格式以下:

[loop_label:] LOOP
    statement_list
END LOOP

其中loop_label表示LOOP語句的標註名稱,該參數能夠省略;statement_list參數表示須要循環執行的語句

四、LEAVE

LEAVE語句用來退出任何被標註的流程控制構造,LEAVE語句的基本格式以下:

LEAVE label

五、ITERATE

ITERATE語句將執行順序轉到語句段開頭出,語句基本格式以下:

ITERATE label

六、REPEAT

REPEAT語句用來建立一個帶有條件判斷的循環過程,每次與局執行完畢以後,會對條件表達式進行判斷,若是表達式爲真,則循環結束,不然重複執行循環中的語句。REPEAT語句的基本格式以下:

[repeat_label:] REPEAT
    statement_list
UNTIL expr_condition
END REPEAT

其中,repeat_label爲REPEAT語句的標註名稱,該參數能夠省略;REPEAT語句內的語句或語句羣被重複,直至expr_condition爲真

 

調用存儲過程和函數

存儲過程已經定義好了,接下來無非就是調用。存儲過程和函數有不少種調用方法,存儲過程必須使用CALL語句調用,而且存儲過程和數據庫相關,若是要執行其餘數據庫中的存儲過程,須要指定數據庫名稱,例如CALL dbname.procname。存儲函數的調用與MySQL中預約義的函數調用方式相同。

一、調用存儲過程

存儲過程是經過CALL語句進行調用的,語法以下:

CALL sp_name([parameter[,...]])

舉個例子,就調用最前面那個CountStudent的存儲過程:

CALL CountStudent('Bruce', @num);
select @num;

運行結果爲:

二、調用存儲函數

MySQL中調用存儲函數的使用方法和MySQL內部函數的使用方法是同樣的,無非存儲函數是用戶本身定義的,內部函數是MySQL開發者定義的。

咱們調用一下上面定義的NameByZip那個函數:

select NameByZip();

運行結果爲:

能夠對照一下,studenName爲"James"這一條,對應的studentPhone就是"44444444",符合SELECT出來的結果

 

查看、刪除存儲過程和函數

一、查看存儲過程和函數的狀態

SHOW STATUS能夠查看存儲過程核函數的狀態,其基本語法結構以下:

SHOW {PROCEDURE | FUNCTIOn} STATUS [LIKE 'pattern'

這個語句是一個MySQL的擴展,他返回子程序的特徵,如數據庫、名字、類型、建立者及建立和修改日期。若是沒有指定樣式,根據使用的語句,全部存儲過程或存儲函數的信息都被列出。PROCEDURE和FUNCTIOn分別表示查看存儲過程和函數,LIKE語句表示匹配存儲過程或函數的名稱。

舉個例子:

SHOW PROCEDURE STATUS

運行結果爲:

後面還有一些字段,截圖截不全沒辦法。查看存儲函數也同樣,能夠本身試試看。

二、查看存儲過程和函數的定義

除了SHOW STATUS外,還可使用SHOW CREATE來查看存儲過程的定義,基本格式爲:

SHOW CREATE {PROCEDURE | FUNCTION} sp_name

好比:

SHOW CREATE FUNCTION NameByZip

我查看了NameByZip這個函數的定義,結果爲:

這個Create Function字段就是建立的存儲函數的內容

三、刪除存儲過程和函數

刪除存儲過程核函數,可使用DROP語句,基本語法以下:

DROP {PROCEDURE | FUNCTION} [IF EXISTS] sp_name

這個語句被用來移除一個存儲過程或函數。sp_name爲待移除的存儲過程或函數的名稱。

IF EXISTS子句是一個MySQL的擴展,若是程序或函數不存儲,它能夠防止錯誤發生,產生一個用SHOW WARNINGS查看的警告。舉個例子:

DROP PROCEDURE CountStudent
DROP FUNCTION NameByZip;

這麼簡單就能夠了。注意這裏沒有講修改存儲過程和存儲函數,由於修改存儲過程或者函數只能修改存儲過程或者存儲函數的特性,不能直接對已有的存儲過程或函數進行修改,若是必需要改,只能先DROP在從新編寫代碼,CREATE一個新的

相關文章
相關標籤/搜索