(九)MySQL存儲過程


1也殖、MySQL存儲過程簡介

在對數(shù)據(jù)庫進行增土思、刪、改忆嗜、查等操作時己儒,實際上輸入的SQL語句會經(jīng)由MySQL引擎分析語法是否正確,之后再編譯成MySQL可識別的命令捆毫,最后執(zhí)行該語句并將結(jié)果返回至客戶端闪湾。

假如能夠?qū)υ摿鞒踢M行簡化,省略語法分析和編譯的環(huán)節(jié)绩卤,那么MySQL的執(zhí)行效率將會大大提高途样。因此首先需要了解什么是存儲過程:

存儲過程是SQL語句和控制語句的預(yù)編譯集合,以一個名稱存儲并作為一個單元處理濒憋。

存儲過程會被儲存在數(shù)據(jù)庫內(nèi)何暇,可以由應(yīng)用程序調(diào)用執(zhí)行,而且允許用戶聲明變量以及進行流程控制凛驮;存儲過程可以接受參數(shù)裆站,包括輸入類型的參數(shù),或輸出類型的參數(shù),并且可以存在多個返回值宏胯。

因此使用存儲過程的效率要比使用單一的SQL語句執(zhí)行的效率要高羽嫡,例如:編寫了兩條SQL的語句,MySQL會對這兩條語句逐一的進行分析肩袍、編譯厂僧,再逐一執(zhí)行;而采用存儲過程以后了牛,只有在第一次執(zhí)行時才進行語法分析和編譯,以后當客戶端再去調(diào)用辰妙,會直接調(diào)用編譯完成的結(jié)果鹰祸,通過省略再次進行語法分析和編譯而提高了執(zhí)行效率。

存儲過程的優(yōu)點:

  1. 增強SQL語句的功能和靈活性
    在存儲過程內(nèi)可以寫控制語句密浑,從而可以完成復(fù)雜的判斷以及較復(fù)雜的運算蛙婴,因此具有很強的靈活性;
  2. 實現(xiàn)較快的執(zhí)行速度
    例如執(zhí)行某個復(fù)雜的操作尔破,當包含大量的sql語句時街图,雖然首次執(zhí)行與不使用存儲過程的效率無差,但以后客戶端再次調(diào)用時便直接從內(nèi)存中來執(zhí)行編譯好的結(jié)果懒构,從而實現(xiàn)了更高的執(zhí)行速度餐济。
  3. 減少了網(wǎng)絡(luò)流量
    當需要通過客戶端發(fā)送SQL語句來使服務(wù)器執(zhí)行某些操作時,如果每次都是發(fā)送單獨的SQL語句胆剧,那么通過http協(xié)議所提交的數(shù)據(jù)量相對而言會比較大絮姆;而使用存儲過程則可以減少數(shù)據(jù)量,從而減少了網(wǎng)絡(luò)流量秩霍。

2篙悯、存儲過程語法結(jié)構(gòu)解析

創(chuàng)建存儲過程
CREATE
[DEFINER = { user | CURRENT_USER }]
PROCEDURE sp_name ([proc_parameter[,……]])
[characteristic ……] routine_body

proc_parameter:
[ IN | OUT | INOUT ] param_name type

COMMENT ' STRING ':
| { CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA } | SQL SECURITY { DEFINER | INVOKER }

可以理解為:
 創(chuàng)建存儲過程
 創(chuàng)建者,省略即為當前登錄到MySQL的用戶
 過程名 前置選項 參數(shù)
 特性 過程體

前置選項:

  • IN铃绒,表示該參數(shù)的值必須在調(diào)用存儲過程時指定鸽照,在存儲過程中不能被返回;
  • OUT颠悬,表示該參數(shù)的值可以被存儲過程改變矮燎,并且可以返回;
  • INOUT赔癌,表示該參數(shù)在在調(diào)用存儲過程時指定漏峰,并且可以被存儲過程改變和返回。

關(guān)于特性:

  • CONTAINS SQL:包含SQL語句届榄,但不包含讀或?qū)憯?shù)據(jù)的語句浅乔;
  • NO SQL:不包含SQL語句;
  • READS SQL DATA:包含讀數(shù)據(jù)的語句;
  • MODIFIES SQL DATA:包含寫數(shù)據(jù)的語句靖苇;
  • SQL SECURITY { DEFINER | INVOKER }:指明誰有權(quán)限來執(zhí)行席噩。

關(guān)于過程體:

  1. 過程體由合法的SQL語句構(gòu)成;
  2. 過程體可以是近乎任意的SQL語句贤壁;
  3. 過程體如果為復(fù)合結(jié)構(gòu)悼枢,則使用BEGIN……END語句包含;
  4. 復(fù)合結(jié)構(gòu)可以包含聲明脾拆、循環(huán)馒索、控制結(jié)構(gòu)。

3名船、創(chuàng)建不帶參數(shù)的存儲過程

以函數(shù)VERSION()為例绰上,創(chuàng)建可以返回版本信息的存儲過程:

之后就可以調(diào)用該存儲過程了,調(diào)用的方式有兩種:

CALL sp_name([parameter[,……]])
CALL sp_name[()]
區(qū)別:如果存儲過程在封裝時沒有參數(shù)渠驼,“()”有或沒有都可以蜈块;但是當存儲過程帶有參數(shù),就必須有“()”迷扇。

因此對于不帶有參數(shù)的存儲過程sp1而言百揭,兩種調(diào)用方式都可以:



4、創(chuàng)建帶有IN類型參數(shù)的存儲過程

創(chuàng)建數(shù)據(jù)表users:

此次共填入了18條記錄蜓席,手動輸入過于繁瑣器一,因此提供源碼,點擊下載使用厨内。

之后需要使用帶有IN類型的存儲過程來刪除用戶指定的“id”號的用戶數(shù)據(jù)盹舞,按照慣例,首先需要修改分隔符隘庄,之后創(chuàng)建存儲過程:

單行過程體也可以使用BEGIN……END語句包含踢步,而過程體中第一個“id”是指數(shù)據(jù)表中的字段,第二個“id”是傳入存儲過程的參數(shù)丑掺。
  將分隔符改回默認的“获印;”,因為存儲過程有參數(shù)街州,因此使用帶有“()”的調(diào)用方式兼丰,希望刪除“id”為3的用戶記錄,此時“神奇”的事情發(fā)生了唆缴,數(shù)據(jù)表被清空了鳍征,18條記錄全部被刪除:

其實出現(xiàn)這種情況的原因很簡單,雖然我們知道過程體中兩個“id”的區(qū)別面徽,但是對于系統(tǒng)而言無法區(qū)分艳丛,認為兩個都是字段匣掸,因此就全部刪除了,這也說明要注意過程體中的參數(shù)名不能與數(shù)據(jù)表中的字段名相同氮双,而對于存儲過程而言碰酝,只能修改如下幾個簡單的選項:

ALTER PROCEDURE sp_name [characteristic ……]

COMMENT ' STRING ':
| { CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA } | SQL SECURITY { DEFINER | INVOKER }

由于不能修改過程體,因此只能刪除存儲過程再重寫戴差,刪除的語法結(jié)構(gòu)如下:

DROP PROCEDURE [IF EXISTS] sp_name

此時就可以執(zhí)行刪除存儲過程操作送爸,并使用提供下載的原碼將數(shù)據(jù)庫記錄導(dǎo)入了:

重新創(chuàng)建存儲過程:

修改分隔符并查看數(shù)據(jù)表數(shù)據(jù):

因為數(shù)據(jù)被清空的緣故,“id”編號會繼續(xù)排序暖释,此時選擇刪除“id”為23的用戶記錄:

再次搜索“id”為23的用戶顯示數(shù)據(jù)為空袭厂,表明已成功刪除。


5球匕、創(chuàng)建帶有IN和OUT類型參數(shù)的存儲過程

對之前的“removeUserById”這個存儲過程進行升級纹磺,刪除指定的“id”且返回剩余的“id”數(shù)量:

恢復(fù)分隔符并查看數(shù)據(jù)表中現(xiàn)有的“id”數(shù)量:

此時調(diào)用該存儲過程并刪除“id”為27的用戶記錄,另一個參數(shù)“@num”為用戶變量谐丢,用來記錄剩余的“id”數(shù)量,通過查詢可見剩余“id”數(shù)量為16:

關(guān)于變量的相關(guān)內(nèi)容蚓让,可參考(十)MySQL中的變量乾忱。


6、創(chuàng)建帶有多個OUT類型參數(shù)的存儲過程

除了可以通過指定“id”來刪除用戶記錄之外历极,還可以通過例如年齡窄瘟、性別等等其他字段來刪除:

通過查看記錄發(fā)現(xiàn)會有很多年齡相同的用戶,因此創(chuàng)建一個可以根據(jù)年齡來刪除用戶記錄的存儲過程趟卸,且該過程不僅能返回剩余的用戶數(shù)量蹄葱,還能返回刪除的記錄數(shù)量。不過在此之前锄列,先簡單介紹一個能實現(xiàn)該存儲過程的系統(tǒng)函數(shù)ROW_COUNT():

該函數(shù)實際上是返回最近增加图云、刪除、更新等操作影響的行數(shù)邻邮,例如以數(shù)據(jù)表“test”為例:

現(xiàn)向表中再插入兩條記錄后調(diào)用函數(shù)ROW_COUNT():

此時顯示被影響的行數(shù)為2竣况,了解其功能后,再來創(chuàng)建存儲過程:

修改分隔符筒严,查詢原數(shù)據(jù)表的總記錄數(shù)為13丹泉,以及將要刪除的年齡為23的用戶記錄數(shù)為4:

理論上執(zhí)行完存儲過程后,剩余的記錄數(shù)應(yīng)為9:

其中變量@var1為刪除記錄數(shù)鸭蛙,變量@var2為剩余記錄數(shù)摹恨,可見該存儲過程已成功執(zhí)行。


7娶视、存儲過程與自定義函數(shù)的區(qū)別

  1. 存儲過程實現(xiàn)的功能要復(fù)雜一些晒哄,而函數(shù)的針對性更強;
  2. 存儲過程可以返回多個值,而函數(shù)只能有一個返回值揩晴;
  3. 存儲過程一般獨立的執(zhí)行勋陪,而函數(shù)可以作為其他SQL語句的組成部分出現(xiàn)。

8硫兰、MySQL存儲過程的SQL語句匯總:

  • 創(chuàng)建存儲過程
    CREATE
    [DEFINER = { user | CURRENT_USER }]
    PROCEDURE sp_name ([proc_parameter[,……]])
    [characteristic ……] routine_body
  • 調(diào)用存儲過程
    CALL sp_name([parameter[,……]])
    CALL sp_name[()]
    區(qū)別:如果存儲過程在封裝時沒有參數(shù)诅愚,“()”有或沒有都可以;但是當存儲過程帶有參數(shù)劫映,就必須有“()”违孝。

  • 簡單修改存儲過程
    ALTER PROCEDURE sp_name [characteristic ……]
    COMMENT ' STRING ':
    | { CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA } | SQL SECURITY { DEFINER | INVOKER }

  • 刪除存儲過程
    DROP PROCEDURE [IF EXISTS] sp_name


版權(quán)聲明:歡迎轉(zhuǎn)載,歡迎擴散泳赋,但轉(zhuǎn)載時請標明作者以及原文出處雌桑,謝謝合作!             ↓↓↓
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末祖今,一起剝皮案震驚了整個濱河市校坑,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌千诬,老刑警劉巖耍目,帶你破解...
    沈念sama閱讀 212,383評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異徐绑,居然都是意外死亡邪驮,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,522評論 3 385
  • 文/潘曉璐 我一進店門傲茄,熙熙樓的掌柜王于貴愁眉苦臉地迎上來毅访,“玉大人,你說我怎么就攤上這事盘榨∮鞔猓” “怎么了?”我有些...
    開封第一講書人閱讀 157,852評論 0 348
  • 文/不壞的土叔 我叫張陵草巡,是天一觀的道長磷斧。 經(jīng)常有香客問我椿访,道長怠堪,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,621評論 1 284
  • 正文 為了忘掉前任姆另,我火速辦了婚禮萍歉,結(jié)果婚禮上侣颂,老公的妹妹穿的比我還像新娘。我一直安慰自己枪孩,他們只是感情好憔晒,可當我...
    茶點故事閱讀 65,741評論 6 386
  • 文/花漫 我一把揭開白布藻肄。 她就那樣靜靜地躺著,像睡著了一般拒担。 火紅的嫁衣襯著肌膚如雪嘹屯。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,929評論 1 290
  • 那天从撼,我揣著相機與錄音州弟,去河邊找鬼。 笑死低零,一個胖子當著我的面吹牛婆翔,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播掏婶,決...
    沈念sama閱讀 39,076評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼啃奴,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了雄妥?” 一聲冷哼從身側(cè)響起最蕾,我...
    開封第一講書人閱讀 37,803評論 0 268
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎老厌,沒想到半個月后瘟则,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,265評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡梅桩,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,582評論 2 327
  • 正文 我和宋清朗相戀三年壹粟,在試婚紗的時候發(fā)現(xiàn)自己被綠了拜隧。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片宿百。...
    茶點故事閱讀 38,716評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖洪添,靈堂內(nèi)的尸體忽然破棺而出垦页,到底是詐尸還是另有隱情,我是刑警寧澤干奢,帶...
    沈念sama閱讀 34,395評論 4 333
  • 正文 年R本政府宣布痊焊,位于F島的核電站,受9級特大地震影響忿峻,放射性物質(zhì)發(fā)生泄漏薄啥。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 40,039評論 3 316
  • 文/蒙蒙 一逛尚、第九天 我趴在偏房一處隱蔽的房頂上張望垄惧。 院中可真熱鬧,春花似錦绰寞、人聲如沸到逊。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,798評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽觉壶。三九已至脑题,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間铜靶,已是汗流浹背叔遂。 一陣腳步聲響...
    開封第一講書人閱讀 32,027評論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留旷坦,地道東北人掏熬。 一個月前我還...
    沈念sama閱讀 46,488評論 2 361
  • 正文 我出身青樓,卻偏偏與公主長得像秒梅,于是被迫代替她去往敵國和親旗芬。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,612評論 2 350

推薦閱讀更多精彩內(nèi)容