mysql 存儲過程

存儲過程是一個SQL語句集合,當主動去調用存儲過程時,其中內部的SQL語句會按照邏輯執行。html


1、建立存儲過程

delimiter $$
create procedure p1()
BEGIN
    select * from t1;
END $$
delimiter ;

這裏建立存儲過程與建立視圖要進行區別,建立視圖 create view, 建立存儲過程 create procedure;並且建立存儲過程的時候在存儲過程名字後面要加上 括號python

對於存儲過程,能夠接收參數,其參數有三類:mysql

  • in          僅用於傳入參數用
  • out        僅用於返回值用
  • inout     既能夠傳入又能夠看成返回值

在navicat中建立的存儲過程:sql

image


2、使用存儲過程

call p1()

注意:ide

使用的關鍵字 call函數

無參數存儲過程

無參數的存儲國過程,直接使用 call 存儲過程名();fetch

有參數存儲過程

一、in 僅用於傳入參數用

delimiter $$
drop procedure if exists p1;
create procedure p1(
	in i1 int
)
BEGIN
declare d1 int;
declare d2 int default 3;
set d1 = i1 + d2;

select * from part where nid > d1;
end $$
delimiter ;

使用:ui

call p1(1);

說明:spa

一、in:定義的參數只能由執行函數的時候傳入,而後即可在函數中使用,同時要注意,當咱們在建立的時候定義參數的類型,那麼在傳遞參數的時候,類型必須一直,否則會報錯。上面列在,定義的參數是 int,因此咱們在執行方法的時候咱們只能傳int類型(整型)的數據。code

二、declare:在方法內部定義變量使用的關鍵字(和js中var區別理解)

三、set:對變量進行設置值的時候,必須使用的。

四、delimiter:從新定義方法內部的結束符號,在sql中通常一個完成sql執行完以後都會使用分號「;」;進行結束,可是在定義存儲過程的時候,內部定義變量、設置值、內部sql語句,都會造成一個完成的語句,而結尾就應該使用分號「;」結束,可是若是直接用分號結束那麼會致使整個sql語句的結束,這樣會致使sql語句執行不完整,所以的在函數內部定義一個符號。讓其在函數內部表示一個語句的執行完成。而不會致使整個sql語句的結束。

代碼中,開始定義了內部的執行結束的表示符號爲 「$$」。而在結尾必須將其變會 「;」,否則會影響後面語句的執行。

五、drop procedure if exists p1; 這句表示先檢測是否存在 p1存儲過程,若是存在則刪除。注意:其中 if exists 是判斷的關鍵。


二、out 僅用於返回值用

delimiter $$
DROP PROCEDURE
IF EXISTS p1$$

CREATE PROCEDURE p1 (IN i1 INT, OUT i2 INT)
BEGIN

DECLARE d2 INT DEFAULT 3 ;
IF i1 = 1 THEN

SET i2 = 100 + d2 ;
ELSEIF i1 = 2 THEN

SET i2 = 200 + d2 ;
ELSE

SET i2 = 1000 + d2 ;
END
IF ; END$$
delimiter ;

在代碼中如今有2個參數,第一個 in 是必傳的,可是 out 並非必傳的,從它的定義上來講,它只是接收方法返回值。

問題:既然是接收返回值,那怎麼接收那?

call p1(1, @u);

這裏要涉及一個回話變量回話變量:至關於咱們在方法外面定義一個變量,而後將變量的 引用 傳入方法。

既然是在外部定義的,那麼就能夠直接訪問這個變量。

call p1(1, @u);
select @u;

結果:

image

說明:

sql中查看某個變量要使用 select。格式:select 變量名


三、inout     既能夠傳入又能夠看成返回值

delimiter $$
DROP PROCEDURE IF EXISTS p1$$

CREATE PROCEDURE p1 (
	IN i1 INT,
	INOUT i3 INT,
	OUT i2 INT
)
BEGIN

	DECLARE d2 INT DEFAULT 3 ;
	SET i3 = i3 + 1 ;
	IF i1 = 1 THEN

	SET i2 = 100 + d2 ;
	ELSEIF i1 = 2 THEN

	SET i2 = 200 + d2 ;
	ELSE

	SET i2 = 1000 + d2 ;
	END
	IF ; 
END$$
delimiter ;

inout是必傳字段。執行代碼是要注意,inout既然是能傳值也能獲取值,就不能單單的傳一個對應類型的值進去就好了的。

set @x = 5;
call p1(1, @x, @u);
select @x,@u;

結果:

image

說明:

一、in 是必傳字段。

二、out 能夠不用傳。可是若是想獲取返回值的話,那就必須傳。

三、inout:也是必傳字段。


3、修改存儲過程

修改存儲過程很麻煩,所以通常不修改存儲過程,而是直接刪除,從新建立一個新的存儲過程。


4、刪除存儲過程

drop procedure proc_name;


5、pymysql執行存儲過程

建立存儲過程:

delimiter $$
drop PROCEDURE if EXISTS p1;
create PROCEDURE p1(
	in i1 int,
	inout i2 int,
	out i3 int
)
BEGIN
	DECLARE d1 int default 3;
	set i2 = i2 + 1;
	select * from part WHERE nid > i2;
	if i1 = 1 then
		set i2 = 100 + d1;
	ELSEIF i1 = 2 THEN
		set i2 = 200 + d1;
	else
		set i2 = 1000 + d1;
	end if;
end $$
delimiter ;

存儲過程

問題:在python中怎樣獲取方法返回的東西?

一、獲取方法中sql語句操做的結果。

# !usr/bin/evn python

import pymysql

conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='', db='waijian')
cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)

# 執行存儲過程
row = cursor.callproc('p1', args = (1,2,3))
# 獲取存儲過程當中sql語句操做的結果
ret = cursor.fetchall()

print(ret)

# 獲取存儲過程的返回值,括號中的三個參數對應執行存儲過程當中接收的三個參數
effect_row = cursor.execute("select @_p1_0, @_p1_1, @_p1_2")

# 取返回值
r = cursor.fetchone()
print(r)

conn.commit()
cursor.close()
conn.close()
pymysql

執行結果:

image

說明:

一、pymysql執行語句中,傳入參數爲3個,前面分析,out不是必傳字段。所以按上面這樣操做,即便傳了值在程序中,第三個值也會自動被忽略。

二、存儲方法中的sql語句返回的結果是存在與 cursor(遊標)中的。所以獲取時只能經過遊標獲取,代碼中只有一條查詢語句,若是有多條的話,fetchall() 一次性獲取全部的,fetchone() 一條條的獲取。

三、sql語句中的 if判斷語句,主要要和python中的區別記憶。

四、接收方法中返回參數, cursor.execute("select @_p1_0, @_p1_1, @_p1_2");代碼是這句,注意括號中接收參數的寫法,寫法不對獲取結果都爲 none。

以前我使用的是 @_proc_p1_0,@_proc_p1_1,@_proc_p1_2;結果獲取的都爲None,後面改了名字就能夠了。

python 獲取存儲過程當中的信息,要分2步,獲取查詢是一步,獲取返回值是一步,注意區分。


6、擴展

當在存儲過程當中,執行多條sql語句,而且某些sql語句執行的條件,是基於別的sql語句執行的結果。

  • 固然能夠經過連表操做獲取對應的信息。
  • 可是這裏討論的是在存儲過程當中實現

image

注意:

上面代碼中 into 是關鍵。

相關文章
相關標籤/搜索