摘要:存儲過程和函數是在數據庫中定義一些SQL語句的集合,然後直接調用這些存儲過程和函數來執行已經定義好的SQL語句。存儲過程和函數可以避免開發人員重復的編寫相同的SQL語句。而且,存儲過程和函數是在MySQL服務器中存儲和執行的,可以減少客戶端和服務器端的數據傳輸。
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標志。
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)、帶IN的存儲過程
//創建儲存過程.cmd 中運行 CREATE PROCEDURE SP_SEARCH(IN p_name CHAR(20)) BEGIN IF p_name is null or p_name='' THEN SELECT * FROM t_user; ELSE SELECT * 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) BEGIN IF p_name is null or p_name='' THEN SELECT * FROM t_user; ELSE SELECT * 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) BEGIN SET p_num=p_num*10; END //調用並輸出結果 SET @p_num=2; call sp_inout(@p_num); SELECT @p_num;輸出結果:
存儲過程體中可以使用各種sql語句和過程式語句的組合,來封裝數據庫應用中復雜的業務邏輯和處理規則,以實現數據庫應用的靈活編程。下面主要介紹幾個用於構造存儲過程體的常用語法元素。
1、局部變量
在存儲過程體中可以聲明局部變量,用來存儲存儲過程體中臨時結果。
DECLARE var_name[,…] type [DEFAULT value] Var_name:指定局部變量的名稱 Type:用於聲明局部變量的數據類型 default子句:用於為局部變量指定一個默認值。若沒有指定,默認為null.如:
Declare cid int(10);使用說明:
Set var_name=expr Set cid=910;3、select … into 語句
Select col_name[,…] into var_name[,…] table_expr Col_name:用於指定列名 Var_name:用於指定要賦值的變量名 Table_expr:表示select語句中的from字句及後面的語法部分說明:存儲過程體中的select…into語句返回的結果集只能有一行數據。
4、定義處理程序
是事先定義程序執行過程中可能遇到的問題。並且可以在處理程序中定義解決這些問題的辦法。這種方式可以提前預測可能出現的問題,並提出解決方法。
DECLARE handler_type HANDLER FOR condition_value[,…] sp_statement handler_type:CONTINUE | EXIT | UNDO Condition_value:Sqlwarning | not found | sqlexception5、流程控制語句
If search_condition then statement_list [elseif search_condition then statement_list]… [else statement_list] End ifSearch_condition參數:條件判斷語句
多重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)) BEGIN IF p_level ='A' THEN SELECT * FROM t_grade WHERE STU_SCORE >=90; ELSEIF p_level ='B' THEN SELECT * FROM t_grade WHERE STU_SCORE <90 AND STU_SCORE>=80; ELSEIF p_level ='C' THEN SELECT * FROM t_grade WHERE STU_SCORE <80 AND STU_SCORE>=70; ELSEIF p_level ='D' THEN SELECT * FROM t_grade WHERE STU_SCORE <60; ELSE SELECT * FROM t_grade; END IF; END
//調用並輸出結果 CALL SP_SCHOLARSHIP_LEVEL('A');
Case case_value When when_value then statement_list [When when_value then statement_list]… [else statement_list] End case表達形式2
Case When search_condition then statement_list End case使用范例
CREATE PROCEDURE SP_SCHOLARSHIP_LEVEL3(IN p_level char(1)) BEGIN DECLARE p_num int DEFAULT 0; CASE p_level WHEN 'A' THEN SET p_num=90; WHEN 'B' THEN SET p_num=80; WHEN 'C' THEN SET p_num=70; WHEN 'D' THEN SET p_num=60; ELSE SET 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 do Statement_list End 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:] repeat Statement_list Until search_condition End repeat [end_label]Repeat語句首先執行statement_list中的語句,然後判斷條件search_condition是否為真,倘若為真,則結束循環,若不為真,繼續循環。
//帶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;
Call sp_name([parameter[,…]]); Sp_name被調用存儲過程的名稱 Parameter:指定調用存儲過程所要使用的參數。
Alter procedure proc_name[characteristic…]
Drop procedure [if exists] sp_name;
MySQL中,創建存儲函數的基本形式如下:
CREATE FUNCTION sp_name([func_parameter[,...]]) RETURNS type [characteristic ...] routine_body Return
子句用於聲明存儲函數返回值的數據類型。存儲過程是用戶定義的一系列sql語句的集合,涉及特定表或其它對象的任務,用戶可以調用存儲過程,而函數通常是數據庫已定義的方法,它接收參數並返回某種類型的值並且不涉及特定用戶表。
調用存儲函數
Select sp_name([func_parameter…]) Select fn_search(2);刪除存儲函數drop
(比較大小 ,返回大的數)
/**函數使用**/ CREATE FUNCTION sp_cal_max(p_num1 INT,p_num2 INT) RETURNS INT BEGIN IF p_num1 >= p_num2 THEN RETURN p_num1; ELSE RETURN p_num2; END IF; END調用:
SET @p_num1=2; SET @p_num2=34; SELECT sp_cal_max(@p_num1,@p_num2);
1)一般來說,存儲過程實現的功能要復雜一點,而函數的實現的功能針對性比較強。存儲過程,功能強大,可以執行包括修改表等一系列數據庫操作;用戶定義函數不能用於執行一組修改全局數據庫狀態的操作。
2)對於存儲過程來說可以返回參數,如記錄集,而函數只能返回值或者表對象。函數只能返回一個變量;而存儲過程可以返回多個。存儲過程的參數可以有IN,OUT,INOUT三種類型,而函數只能有IN類~~存儲過程聲明時不需要返回類型,而函數聲明時需要描述返回類型,且函數體中必須包含一個有效的RETURN語句。
3)存儲過程,可以使用非確定函數,不允許在用戶定義函數主體中內置非確定函數。
4)存儲過程一般是作為一個獨立的部分來執行( EXECUTE 語句執行),而函數可以作為查詢語句的一個部分來調用(SELECT調用),由於函數可以返回一個表對象,因此它可以在查詢語句中位於FROM關鍵字的後面。 SQL語句中不可用存儲過程,而可以使用函數。
查詢語句可能查詢出多條記錄,在存儲過程和函數中使用光標標來逐條讀取查詢結果集中的記錄。光標的使用包括聲明光標、打開光標、使用光標和關閉光標。光標必須聲明光標、打開光標、使用光標和關閉光標。光標必須聲明在處理程序之前,並且聲明在變量和條件之後。
1 聲明光標
Declare cursor_name cursor forselect_statement; Cursor_name:光標名稱 Select_statement:select語句的內容 Declare cur_employee cursor forselect name,age from employee;
2 打開光標
Open cursor_name Open 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語句打開。
(將表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()
這是表1