前言
本章我們將學(xué)習(xí)數(shù)據(jù)庫(kù)中的存儲(chǔ)過(guò)程,了解什么是存儲(chǔ)過(guò)程,以及在MySQL中創(chuàng)建和調(diào)用存儲(chǔ)過(guò)程。
存儲(chǔ)過(guò)程是什么
存儲(chǔ)過(guò)程(Stored Procedure)是在數(shù)據(jù)庫(kù)系統(tǒng)中,一組為了完成特定功能的SQL 語(yǔ)句集,它存儲(chǔ)在數(shù)據(jù)庫(kù)中,一次編譯后永久有效,用戶(hù)調(diào)用存儲(chǔ)過(guò)程并傳遞參數(shù)來(lái)執(zhí)行它。
存儲(chǔ)過(guò)程的優(yōu)點(diǎn)
存儲(chǔ)過(guò)程是數(shù)據(jù)庫(kù)中的重要組件,具有以下優(yōu)點(diǎn):
重復(fù)使用
存儲(chǔ)過(guò)程一旦定義后,用戶(hù)可以反復(fù)調(diào)用,不需要重寫(xiě)編寫(xiě)SQL語(yǔ)句。
安全
存儲(chǔ)過(guò)程通過(guò)參數(shù)傳入數(shù)據(jù),避免了SQL注入攻擊,同時(shí)可以給存儲(chǔ)過(guò)程配置權(quán)限,只讓特定的用戶(hù)使用。
減少網(wǎng)絡(luò)流量
調(diào)用存儲(chǔ)過(guò)程時(shí),只需要傳遞調(diào)用存儲(chǔ)過(guò)程名稱(chēng)和參數(shù),不需要發(fā)送SQL語(yǔ)句,因此減少了網(wǎng)絡(luò)流量,提高了調(diào)用的速度。
存儲(chǔ)過(guò)程的語(yǔ)法
創(chuàng)建視圖
delimiter //
create procedure 存儲(chǔ)過(guò)程名([in|out|inout]參數(shù)名 類(lèi)型....)
begin
SQL 語(yǔ)句;
end//
delimiter ;
語(yǔ)法說(shuō)明:
delimiter//
是將SQL代碼的結(jié)束符號(hào)設(shè)置為//,因?yàn)榇鎯?chǔ)過(guò)程中有多條SQL語(yǔ)句以分號(hào)結(jié)束,如果定義存儲(chǔ)過(guò)程也以分號(hào)結(jié)束,就存在混淆,所以先將//作為定義存儲(chǔ)過(guò)程的結(jié)束符號(hào),創(chuàng)建完成后再定義為原來(lái)的分號(hào)。
[in|out|inout]
參數(shù)前可以添加in、out、inout關(guān)鍵字設(shè)置參數(shù)的類(lèi)型:
in 代表輸入?yún)?shù),用于傳入數(shù)據(jù),默認(rèn)
out 代表輸出參數(shù),用于返回?cái)?shù)據(jù),類(lèi)似return的作用
inout 代表輸入和輸出都可以
刪除視圖
drop procedure 存儲(chǔ)過(guò)程名;
調(diào)用存儲(chǔ)過(guò)程
call 存儲(chǔ)過(guò)程名(參數(shù))
代碼案例:
-- 刪除存儲(chǔ)過(guò)程
drop procedure if exists pd_select_student;
-- 定義無(wú)參的存儲(chǔ)過(guò)程
delimiter //
create procedure pd_select_student()
begin
select * from tb_student;
end//
delimiter ;
-- 調(diào)用存儲(chǔ)過(guò)程
call pd_select_student();
--定義帶參數(shù)的存儲(chǔ)過(guò)程
drop procedure if exists pd_select_student_by_name;
delimiter //
create procedure pd_select_student_by_name(s_name nvarchar(20))
begin
select * from tb_student where stu_name = s_name;
end//
delimiter ;
call pd_select_student_by_name('李四');
-- 定義通過(guò)學(xué)號(hào)修改學(xué)生姓名、年齡、性別的存儲(chǔ)過(guò)程
drop procedure if exists pd_update_student;
delimiter //
create procedure pd_update_student(s_id int,s_name varchar(20),s_gender varchar(20),s_age int)
begin
update tb_student set stu_name = s_name,stu_gender=s_gender,stu_age=s_age where stu_id = s_id;
end//
delimiter ;
call pd_update_student(1,'張三','女',18);
帶返回值的存儲(chǔ)過(guò)程
存儲(chǔ)過(guò)程也可以返回值給調(diào)用者,實(shí)現(xiàn)步驟是:
用out定義輸出參數(shù)
在存儲(chǔ)過(guò)程內(nèi)部,使用into將查詢(xún)結(jié)果賦值給輸出參數(shù)
調(diào)用存儲(chǔ)過(guò)程前,定義變量,將變量作為輸出參數(shù)
-- 查詢(xún)年齡在一定范圍內(nèi)學(xué)生的人數(shù)
-- 使用out定義輸出參數(shù)
create procedure pd_get_count_by_age(min_age int,max_age int,
out count int)
begin
-- 使用into語(yǔ)句將返回值賦值給輸出參數(shù)
select count(*) into count from tb_student where stu_age between
min_age and max_age;
end//
delimiter ;
-- 定義變量
set @stu_count = 0;
-- 調(diào)用存儲(chǔ)過(guò)程時(shí),傳入變量
call pd_get_count_by_age(10,80,@stu_count);
-- 顯示變量
select @stu_count '人數(shù)';
總結(jié)
存儲(chǔ)過(guò)程可以封裝多條SQL語(yǔ)句,保存在數(shù)據(jù)庫(kù)中,可以被重復(fù)調(diào)用,執(zhí)行效率高、安全性也比較高,是軟件開(kāi)發(fā)中常用的數(shù)據(jù)庫(kù)技術(shù),但是大量的存儲(chǔ)過(guò)程也會(huì)給項(xiàng)目帶來(lái)較多的維護(hù)成本。