一、基本介紹
存儲過程和函數是事先經過編譯並存儲在數據庫中的一段SQL語句的集合,減少數據在數據庫和應用服務之間的傳輸,對於提高數據處理的效率是有好處的。
存儲過程和函數的區別在於 函數必須有返回值,而存儲過程沒有,存儲過程的參數可以使用IN、OUT、INOUT類型,而函數的參數只能是IN類型的。如果有函數從其他類型的數據庫遷移到MySQL,可能需要將函數改造成存儲過程。
存儲過程和函數允許包含DDL語句,也允許使用事務,還可以調用其他的存儲過程和函數,但不允許執行 Load Data Infile 語句;
二、相關操作
創建存儲過程或函數需要 CREATE ROUTINE 權限,修改或刪除存儲過程或函數需要 ALTER ROUTINE 權限,執行存儲過程或函數需要 EXECUTE 權限。
創建、修改存儲過程或函數
Create procedure sp_name([proc_parameter[,…])
[characteristic…] routine_body
Create function sp_name([func_parameter[,…])
Returns type
[characteristic…] routine_body
Return xxx
調用語法:call sp_name([parameter[,…])
參數說明:
pro_parameter
[ IN | OUT | INOUT ] param_name type
func_parameter
param_name type
存儲過程和函數中不允許執行 LOAD DATA INFILE 語句。
Delimiter $$ 修改命令結束符
Characteristic特征值:
Language sql 說明下面body是使用sql編寫,系統默認
Sql security{ definer | invoker } 可以指定子程序該用創建子程序者的許可來執行還是使用調用者的權限執行。默認是definer
Comment ‘string’ 存儲過程或函數的注釋信息
{ Contains sql | no sql | reads sql data | modifies sql data} 供子程序使用數據的內在信息,目前只提供給服務器,並沒有根據這些特征值來約束過程實際使用數據的情況,默認是contains sql;
-
- Contains sql 表示子程序不包含讀或寫數據的語句。
- No sql 表示子程序不包含sql語句。
- Reads sql data 表示子程序包含讀數據的語句,但不包含寫數據的語句。
- Modifies sql data 表示子程序包含寫數據的語句。
實例:
返回值用 @xxx
刪除存儲過程或函數:
一次只能刪除一個存儲過程或函數,需 ALTER ROUTINE 權限
Drop procedure name;
查看存儲過程或者函數:
查看存儲過程或函數的狀態:
Show { procedure | function } status [like ‘pattern’];
查看存儲過程或函數的定義:
Show create { procedure | function } name;
通過查看information_schema.Routines了解存儲過程和函數的信息
Select * from Routines where routine_name = “name”;
三、變量的使用
變量不區分大小寫
變量的定義
Declare 定義一個局部變量,作用域在 BEGIN … END 塊中,可以用在嵌套的塊中。必須寫在復合語句的開頭,並且在任何其他語句的前面。可一次聲明多個相同類型的變量。如需要,可以使用default賦默認值。
Declare var_name[,…] type [default value];
變量的賦值
變量可以直接賦值,或者通過查詢賦值。直接賦值使用set,可以賦常量或者賦表達式。
Set var_name = expr [,var_name = expr] …
Select col_name [,…] INTO var_name [,…] from xxx….; #查詢結果必須只有一行
Set @a = xxx; 相當於全局變量
定義條件和處理:
處理過程中遇到問題時相應的處理步驟。
條件定義
Declare condition_name CONDITION FOR condition_value
條件處理(游標中有實例)
Declare handler_type HANDLER FOR condition_value [,…] sp_statement
說明:
Handler_type 目前支持 continue 和 exit ,continue繼續執行下面的語句,exit表示終止。
Condition_value 值可以通過declare定義的 condition_name,可以是SQLSTATE 的值或者mysql-error-code的值或SQLWARING、NOT FOUND、SQLEXECEPTION,這3個值是3種定義好的錯誤類別。
- SQLWARING 是對所有以01開頭的SQLSTATE代碼速記
- NOT FOUND 是對所有以02開頭的SQLSTATE 代碼速記
- SQLEXCEPTION 是對所有沒有被SQLWARING 或 NOT FOUND 捕獲的SQLSTATE 代碼速記
四、游標的使用
對結果集進行循環的處理,包括光標的聲明、open、fetch 和 close。
1條sql,對應N條結果集的資源,取出資源接口/句柄,就是游標,沿着游標,可以一次取出1行。好處是,每一行的處理權利在我們手中。
游標通俗來講相當於你買東西別人一件件的給你,而不是一下子全給你。
執行沒有數據錯誤:
修改存儲過程:
BEGIN DECLARE row_id int; DECLARE row_dt varchar(50); DECLARE row_catalog int; DECLARE row_total int; DECLARE i int default 1; DECLARE getArticle CURSOR FOR select id,dt,catalog from tblarticle where catalog = 75; select count(*) INTO row_total from tblarticle where catalog=75; OPEN getArticle; WHILE i<=row_total DO FETCH getArticle into row_id, row_dt, row_catalog; SELECT row_id, row_dt, row_catalog; set i = i+1; END WHILE; CLOSE getArticle; END
BEGIN DECLARE row_id int; DECLARE row_dt varchar(50); DECLARE row_catalog int; DECLARE row_total int; DECLARE i int DEFAULT 1; DECLARE getArticle CURSOR FOR select id,dt,catalog from tblarticle where catalog = 75; DECLARE EXIT HANDLER FOR NOT FOUND set i = 0; OPEN getArticle; REPEAT FETCH getArticle into row_id, row_dt, row_catalog; SELECT row_id, row_dt, row_catalog; UNTIL i = 0 END REPEAT; CLOSE getArticle; END
Declare continue/exit handler for not found close 游標名;
Continue 和 exit 的區別:
游標循環讀取的正確邏輯:
五、流程控制
If 、case、loop、leave、iterate、repeat、while語句
If語句
IF search_condition THEN statement_list
[ELSEIF search_condition THEN statement_list]…
[ELSE statement_list]
END IF ;
While語句
WHILE search_condition Do
Statement_list
END WHILE [end_label] ;
case語句
repeat語句(類似do…while)
While 和 repeat 的區別:
While 是滿足條件才執行循環,repeat是滿足條件退出循環;
While在首次循環執行之前就判斷條件,所以循環最少執行0次,而repeat是在首次執行循環之后才判斷條件,類似do…while,所以循壞最少執行1次;