(9)mysql 中的存儲過程和自定義函數

概述

存儲過程和自定義函數是事先通過編譯並存儲在數據庫中的一段SQL語句的集合。相對普通查詢優勢:html

  • 能夠簡化應用開發人員的工做,可重用。
  • 減小數據庫與應用服務器之間的數據傳輸。
  • 提升了數據處理的效率。
  • 安全性提升。因爲存儲過程也可使用權限控制,並且參數化的存儲過程能夠防止SQL注入攻擊,也在必定程度上保證了安全性。

存儲過程與函數的區別在於函數必須有返回值,而存儲過程沒有,存儲過程的參數可使用in(輸入),out(輸出),inout(輸入輸出),而函數的參數只能是in類型。mysql

建立、修改、調用 存儲過程或函數sql

#建立存儲過程
create procedure sp_name([proc_paramenter[,...]])
    [characteristic ...] routine_body

#proc_parameter: [in|out|inout] param_name type
#type:任何可用的MySQL數據類型
#routine_body:是SQL代碼的內容,能夠用BEGIN...END來表示SQL代碼的開始和結束。
___________________________________________________
#建立函數
create function sp_name([func_parameter[,...]])
    return type
    [characteristic ...]routine_body

___________________________________________________
#修改存儲過程或函數
alter {procedure|function} sp_name [characteristic ...]

___________________________________________________
#調用過程的語句
call sp_name([parameter[,...]]);

___________________________________________________
#刪除存儲過程或函數
drop {procedure|function} [if exists] sp_name;

___________________________________________________
#查看存儲過程或函數狀態
show {procedure|function} status like 'sp_name';

___________________________________________________
#查看存儲過程或函數的定義
show create {procedure|function} sp_name;複製代碼

其中characteristic的取值爲:數據庫

說明
language sql 說明routine_body部分是由SQL語句組成的,當前系統支持的語言爲SQL
[not] deterministic 指明存儲過程執行的結果是否肯定。DETERMINISTIC 表示結果是肯定的。每次執行存儲過程時,相同的輸入會獲得相同的輸出。
{contains sql \no sql \ reads sql data \modifies sql data} 指明子程序使用SQL語句的限制。CONTAINS SQL代表子程序包含SQL語句,可是不包含讀寫數據的語句;NO SQL代表子程序不包含SQL語句;READS SQL DATA:說明子程序包含讀數據的語句;MODIFIES SQL DATA代表子程序包含寫數據的語句。默認狀況下,系統會指定爲CONTAINS SQL。
sql_security{definer\invoker} 指明誰有權限來執行。DEFINER 表示只有定義者才能執行;INVOKER 表示擁有權限的調用者能夠執行。默認狀況下,系統指定爲DEFINER。
comment 'string' 註釋信息,能夠用來描述存儲過程或函數

MySQL的存儲過程或函數中容許包含DDL語句,也容許存儲過程當中執行事務處理。存儲過程和函數中能夠調用其餘的過程或函數。安全

存儲過程及函數基本使用舉例

舉例說明:服務器

delimiter //

create procedure procedure_test(
        in v_min int,in v_max int,out num int)
reads sql data
begin

#查詢出test1表中sid在v_min 和v_max之間的記錄
select * from test1
where sid > v_min and sid < v_max;

#將返回的記錄行數寫入num變量中輸出
select found_rows() into num;

end //

delimiter ;複製代碼

注意:「DELIMITER //」語句的做用是將MYSQL的結束符設置爲//,由於MYSQL默認的語句結束符爲分號;,爲了不與存儲過程當中SQL語句結束符相沖突,須要使用DELIMITER 改變存儲過程的結束符,並以「END //」結束存儲過程。函數

存儲過程定義完畢以後再使用DELIMITER ;恢復默認結束符。DELIMITER 也能夠指定其餘符號爲結束符
建立的存儲過程及test1數據
ui

建立存儲過程

調用存儲過程極其結果
調用存儲過程

輸出變量
輸出存儲過程結果

刪除存儲過程
刪除存儲過程

查看存儲過程
查看存儲過程狀態

查看存儲過程定義
查看存儲過程定義

使用變量舉例

變量的做用範圍只能在begin...end塊中,能夠用在嵌套中。變量的定義必須寫在複合語句的開頭,而且在任何其餘語句的前面。能夠一次聲明多個相同類型的變量。
(10)mysql中的變量-參考連接spa

#建立一個函數返回v_min、v_max之間的sid之和。
delimiter //
create function function_test
    (v_min int,v_max int)
returns int
reads sql data
begin
declare temp int;
select sum(sid) into @temp
from test1
where sid > v_min and sid < v_max;
return @temp
end //

delimiter ;複製代碼

建立結果:
.net

建立函數

調用函數執行結果
調用自定義函數

使用條件定義、處理

條件定義和處理能夠用來定義在處理過程當中遇到問題(錯誤,警告,異常)時的處理步驟。條件處理程序定義參見連接以下:
(11)mysql中的條件定義、處理-參考連接

1. 未使用條件定義處理程序

delimiter $

create procedure pro_condition()
begin
set @x=1;
select * from test111;
set @x=2;
end$

delimiter ;複製代碼

結果

調用存儲過程

調用用戶變量

2. 使用了條件定義處理程序

drop procedure if exists pro_condition;

delimiter $

create procedure pro_condition()
begin
declare continue handler for 1146 set @x2=1;
set @x=1;
select * from test111;
set @x=2;
end$

delimiter ;複製代碼

結果:

調用存儲過程

調用用戶變量

使用光標

在存儲過程當中可使用光標對結果集進行循環處理。光標使用參看連接以下:
(12)mysql中的光標-參考連接

DELIMITER $

CREATE PROCEDURE pro_cursor()
BEGIN
DECLARE sid_i INT;
DECLARE cur_test CURSOR FOR SELECT sid FROM test1;
DECLARE EXIT HANDLER FOR NOT FOUND CLOSE cur_test;

SET @x1=0;
SET @x2=0;
OPEN cur_test;
REPEAT
    FETCH cur_test INTO sid_i;
    SET @x1=@x1+sid_i;
    SET @x2=@x2+1;
UNTIL 0 END REPEAT;

CLOSE cur_test;

END $

DELIMITER ;
#查看結果
call pro_cursor();
select @x1,@x2;複製代碼

test1表結構及數據

test1表數據

結果
查詢結果

使用流程控制

存儲過程和函數中可使用流程控制來控制語句的執行。MySQL 中可使用IF 語句、CASE 語句、LOOP語句、LEAVE 語句、ITERATE 語句、REPEAT 語句和WHILE 語句來進行流程控制。具體流程使用參見以下連接:
(13)mysql中的流程控制-參考連接

delimiter $
create procedure pro_flow_control(in sid_v int)
begin
    if sid_v > 5 then
        select * from test1 where sid>5;
    else
        select * from test1 where sid<=5;
    end if;
end $
delimiter ;複製代碼

結果:

sid_v小於5

sid_v大於5

參考

辛星解讀mysql中的存儲過程的優劣

相關文章
相關標籤/搜索