mysql存儲過程詳解


一、什么是存儲過程?

stroed procedure
存儲過程是在數據庫系統中, 一組為了完成特定功能的sql語句集, 靜編譯后存儲在數據庫中,
用戶通過指定存儲過程的名字並給出參數(如果該存儲過程帶有參數)來執行它。

存儲過程不僅僅是"批處理"
存儲過程是經過編譯的sql語句集

二、存儲過程與函數和觸發器的區別?

從語法上看, 存儲過程和函數以及觸發器是十分類似的。我們甚至可以說, 觸發器和函數就是一種特別存儲過程。
不過他們之間還是有一些區別的
1. 觸發器用於完成一些觸發條件所引發的操作。 觸發器的執行是自動化的
2. 自定義函數只能通過return語句返回單個值或者表對象, 而存儲過程不能調用return語句, 但可以通過
out參數返回多個值。函數可以在sql語句中結合使用。 函數不能用臨時表, 只能用表變量, 還有一些
系統函數都不可用等等
3. 存儲過程用於完成一系列的sql操作, 批量化的完成數據庫操作工作, 由使用者調用執行。

 

三、為什么使用存儲過程?

1. 存儲過程只在創造時進行編譯, 以后每次執行存錯過程都不需要在重新編譯, 而一般SQL
語句每執行一次就編譯一次, 所以使用存儲過程可提高數據庫執行速度。

2. 當丟數據庫進行復雜操作時(如對多個表進行Update, Insert, Query, Delete),
可將此復雜操作用存儲過程封裝起來與數據庫提供的事務處理結合一起使用。
這些操作, 如果用程序來完成, 就變成了一條條的sql語句, 可能要多次連接數據庫。而
換成存儲, 就只需要連接一次數據庫就可以了

3. 存儲過程可以重復使用, 可減少數據庫開發人員的工作量。

4. 安全性高, 可設定只有某此用戶才具有對指定存儲過程的使用權。

 

四、為什么不使用存儲過程

1. 可移植性差
2. 對於很簡單的sql語句, 存儲過程沒有優勢
3. 如果存儲過程中不一定會減少網絡傳輸(包含的sql數量並不多, 並且執行很快,就沒必要了)
4. 如果只有一個用戶使用數據庫, 那么存儲過程對於安全也沒什么影響
5. 團隊開發時需要先統一標准, 否則后期維護是個麻煩
6. 在大並發量訪問的情況下, 不宜寫過多涉及運算的存儲過程
7. 業務邏輯復雜時, 特別是涉及到對很大的表進行操作的時候, 不如在前端先簡化業務邏輯

五、查看存儲過程狀態

與查看函數和觸發器一樣, 可是使用show status語句查看存儲過程狀態
show procedure status like 'p%'\G;
select * from information_schema.Routines where routine_name='p1' and routine_type='PROCEDURE'\G;

六、查看存儲過程內容

show create procedure p2\G;

七、例子

delimiter // 定界符, 用於修改結束符, 方便些多條sql語句, 最后在修改回來

create procedure 名稱(out s int)
begin
select count(*) into s from mysql.user;
end

//
delimiter;
call 存儲過程名稱(@s) 執行;
select @s

 

八、存儲過程參數

mysql存儲過程的參數用於存儲過程的定義, 共有三種參數類型, IN, OUT, INOUT,形式如下:
CREATE PROCEDURE (【in|out|inout】 函數名  函數類型...)

IN 輸入參數: 表示該參數的值必須在調用存儲過程時指定, 在存儲過程中修改該參數的值不能被返回, 為默認值。
OUT 輸出參數: 該值可在存儲過程內部被改變, 並可返回。
INOUT輸入輸出參數: 調用時指定, 並且可被改變和返回。

 

IN參數例子:

IN參數的特定在於, 讀取外部變量值, 且有效范圍僅限於存儲過程內部。

例子:
delimiter //
create procedure pin(IN p_in int)
begin
select p_in;
set p_in=2;
select p_in;
end;
//
delimiter;
-----------
set @p_in=1;
call pin(@p_in)   無論內部如何修改, 都不會被傳遞到外部
select @p_in  還是1, 而不是函數修改后的2

 

OUT參數例子

out參數的特點在於, 不讀取外部變量值, 在存儲過程執行完畢后保留新值。

delimiter //
create procedure pout(out p_out int)
begin
select p_out;   不接受參數, 值為null
set p_out = 2;
select p_out;
end;
//
delimiter ;
--------------
set @p_out=1;  這個@就是聲明參數的意思
call pout(@p_out);
如果在查詢
select @p_out; 結果是2

 

INOUT 參數例子

INOUT參數的特點在於, 讀取外部變量值, 在存儲過程執行完畢后保留新值

delimiter //
create procedure pinout(inout p_inout int)
begin
select p_inout;
set p_inout = 2;
select p_inout;
end;
//
delimiter ;

----------
set @p_inout = 1;  先設置值為1, 存儲過程查看
call pinout(@p_inout);
select @p_inout;

 

 

不加參數例子

如果在創建存儲過程時沒有指定參數類型, 則需要調用的時候指定參數值。
delimiter //
create definer=`root`@`localhost` procedure `test1` (n1 int)
begin
set @x=0;
repeat set @x = @x+1;  循環
end repeat;
end;
delimiter;

--------
call test1(10);

 

 

變量定義

{

  1. 局部變量:局部變量一般用在sql語句塊中,比如存儲過程的begin/end。

  2. 用戶變量:用戶變量的作用域要比局部變量要廣。用戶變量可以作用於當前整個連接,但是當當前連接斷開后,其所定義的用戶變量都會消失。

  3. 會話變量:服務器為每個連接的客戶端維護一系列會話變量。

  4. 全局變量:全局變量影響服務器整體操作。當服務器啟動時,它將所有全局變量初始化為默認值

}

一、局部變量

局部變量一般用在sql語句塊中,比如存儲過程的begin/end。其作用域僅限於該語句塊,在該語句塊執行完畢后,局部變量就消失了。

局部變量一般用declare來聲明,可以使用default來說明默認值。

drop procedure if exists add;

create procedure add

(

    in a int,

    in b int

)

begin

    declare c int default 0;

    set c = a + b;

    select c as c;

end;

 

 

mysql 中使用declare 進行變量定義。語法:
delcare variable_name [, variable_name...] datatype [default value];
其中, datatype 為mysql的數據類型, 例如:
int float, date, varchar(length)
例如:
declare i_int int unsigned default 40000;
declare i_varchar varchar(255)defalt "This will not be padded";
也可以
declare var int;
set var  = p1 + 1;

 

二、用戶變量

 

用戶變量的作用域要比局部變量要廣。用戶變量可以作用於當前整個連接,但是當當前連接斷開后,其所定義的用戶變量都會消失。

用戶變量使用如下(這里我們無須使用declare關鍵字進行定義,可以直接這樣使用):

select @變量名

對用戶變量賦值有兩種方式,一種是直接用"="號,另一種是用":="號。其區別在於使用set命令對用戶變量進行賦值時,兩種方式都可以使用;當使用select語句對用戶變量進行賦值時,只能使用":="方式,因為在select語句中,"="號被看作是比較操作符。

示例程序如下:

drop procedure if exists math;

create procedure math

(

    in a int,

    in b int

)

begin

    set @var1 = 1;

    set @var2 = 2;

    select @sum:=(a + b) as sum, @dif:=(a - b) as dif;

end;

執行結果

mysql> call math(3, 4);
+------+------+
| sum  | dif  |
+------+------+
|    7 |   -1 | 
+------+------+
1 row in set (0.00 sec)

Query OK, 0 rows affected (0.00 sec)

mysql> select @var1; //var1為用戶變量
+-------+
| @var1 |
+-------+
| 1     | 
+-------+
1 row in set (0.00 sec)

mysql> select @var2; //var2為用戶變量
+-------+
| @var2 |
+-------+
| 2     | 
+-------+
1 row in set (0.00 sec)

 

更詳細可以參考鏈接:https://www.cnblogs.com/gavin110-lgy/p/5772577.html

 

變量賦值

mysql 中使用set命令進行變量賦值。 語法:
SET 變量名 = 值
注意: 變量賦值是可以在不同存儲過程中繼承的。

例1:
  create procedure p1() set @last_procedure = 'p1';
  create procedure p2() concat('last procedure was ', @last_proc);
  call p1();
  call p2();

 

變量的作用域:

內部的變量是其作用域范圍內享有更高的優先權, 當執行到end, 內部變量消失, 此時已經
在其作用域外, 變量不再可見了。因為在存儲過程外也不能找到這個聲明的變量, 但是你可以通過
out參數或者將其指派給會話變量來保存其值。
內部變量在begin -- end 之間

注釋:

-- 單行注釋
/**/ 多行注釋

 

if 語句

IF  -- THEN  -- ELSE
例子:
delimiter //
create procedure proc2(IN p1 int)
begin
declare var int;
set var=p1 + 1;
IF var = 1 THen insert into t values(11);
end if;    /* if 結束*/

if var = 2 then insert into t values (22);
else insert into values (33);
end if;

end;
//

delimiter ;

 

case 語句

delimiter //
create procedure proc3(IN p1 int)
begin
declare var int;
set var  = p1 + 1;
case var
  when 1 then insert into t values(17);
  when 2 then insert into t values(18);
  else insert into t values(19);
end case;
end;
//
delimiter ;

 

WHILE語句

DELIMITER //
create procedure proc4()
begin
declare var int;
set var=0;
while var < 6 do
  insert into t values(var);
  set var = var + 1;
end while;
end;
//
delimiter;

 

repeat 語句

類似於for循環  又有點類似於c語言的go while, 個人認為

delimiter //
create procedure proce5()
begin
declare v int;
set v=0;
repeat
  insert into t values(v);
  set v = v+1;
  until v < 5
end repeat;
end;
//
delimiter;

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM