MySQL自定義函數(shù)和存儲過程

自定義函數(shù):

概念:用戶自定義函數(shù)(user-defined function,UDF)是一種對 MySQL 擴展的途徑,其用法與內(nèi)置函數(shù)相同。

創(chuàng)建自定義函數(shù)語法結(jié)構(gòu):

CREATE FUNCTION function_name?

RETURNS?

{ STRING | INTEGER | REAL | DECIMAL}

routine_body

函數(shù)體(routine_body):

⑴ 函數(shù)體由合法的 SQL 語句構(gòu)成

⑵ 函數(shù)體可以是簡單的 SELECT 或 INSERT 語句

⑶ 函數(shù)體如果為復(fù)合結(jié)構(gòu)則使用 BEGIN ... END 語句

⑷ 復(fù)合結(jié)構(gòu)可以包含聲明,循環(huán),控制結(jié)構(gòu)

刪除自定義函數(shù)語法結(jié)構(gòu):

DROP FUNCTION [ IF EXISTS ] function_name

案例:

無參函數(shù):

將系統(tǒng)默認返回的日期格式化為年月月時分表

把這個返回格式封裝成一個自定義函數(shù),返回類型為 VARCHAR,返回的函數(shù)體為 DATE_FORMAT():

帶參函數(shù):

創(chuàng)建一個函數(shù) f2,傳入 num1 和 num2 返回它們的平均值

調(diào)用該函數(shù):

帶有復(fù)合結(jié)構(gòu)函數(shù)體的自定義函數(shù):

首先查看下表 tb_user5 的記錄:

如果每次插入記錄都需要寫 INSERT 語句,會有點麻煩。現(xiàn)在把 INSERT 語句封裝成一個函數(shù),并返回當(dāng)前插入的記錄的 ID:

分號 “;” 和系統(tǒng)默認的結(jié)束符沖突,所以通過 DELIMITER $$ 將分隔符修改為 “$$”。由于有多個語句要執(zhí)行,所以需要用 BEGIN ... END 構(gòu)成一個聚合體。

調(diào)用函數(shù) adduser:

返回該條記錄的 ID,再查詢一下表 tb_user5 的記錄:

定義局部變量:

DECLARE?var_name [,varname] ... date_type [DEFAULT?VALUE]

局部變量的作用范圍是在 BEGIN...END 語句中,而且定義局部變量語句必須在 BEGIN...END語句中的第一行定義

為變量賦值:

SET?parameter_name = value [,parameter_name = value...]

SELECT ... INTO?parameter_name

用戶變量語法(可以理解為全局變量):

SET?@param_name = value

流程控制語句:

⑴ IF 語句

? ? 語法結(jié)構(gòu):

? ??IF search_condition THEN statement_list

????[ELSEIF search_condition THEN statement_list] ...

????[ELSE statement_list]

????END IF

? ? 其中,search_condition 表示條件判斷語句,statement_list 表示執(zhí)行語句。

????案例:

????傳入一個參數(shù),根據(jù)數(shù)值判斷返回指定的數(shù)值。

⑵ CASE 語句

? ? 語法結(jié)構(gòu):

????①

? ??CASE case_value

????WHEN when_value THEN statement_list

????[WHEN when_value THEN statement_list] ...

????[ELSE statement_list]

????END CASE

? ? 其中,case_value 表示條件判斷的變量,when_value 表示變量的取值,

????statement_list 表示執(zhí)行語句

? ? 案例:

? ??②

? ??CASE

????WHEN search_condition THEN statement_list

????[WHEN search_condition THEN statement_list] ...

????[ELSE statement_list]

????END CASE

? ? 其中,search_condition 表示條件判斷,statement_list 表示執(zhí)行語句

? ? 案例:

⑶ LOOP 語句

? ? 概念:

????實現(xiàn)一個簡單的循環(huán),沒有結(jié)束循環(huán)語句,需要通過 LEAVE 來停止循環(huán)

? ? 語法結(jié)構(gòu):

????[begin_label:] LOOP

????statement_list

????END LOOP [end_label]

? ? 其中,begin_label 和 end_label 表示開始和結(jié)束的標志可以隨意命名,

????statement_list 執(zhí)行語句。

⑷ LEAVE 語句

? ? 概念:

????結(jié)束本次循環(huán)

? ? 語法結(jié)構(gòu):

? ??LEAVE label

? ? 案例:

? ? 聲明局部變量 a 循環(huán)累加至 10 打印出來。

⑸?ITERATE 語句

? ? 概念:

????跳出本次循環(huán),重新執(zhí)行循環(huán),只能出現(xiàn)在 LOOP,REPEATE,WHILE 循環(huán)中。

? ? 語法結(jié)構(gòu):

? ??ITERATE label

? ? 案例:

????執(zhí)行結(jié)果:

????由圖,聲明兩個局部變量 x,y,循環(huán) x+1 當(dāng) x>10 時結(jié)束本次循環(huán);當(dāng) x=5 時,y = x*2,

? ? 所以 y = 10 ,接著?ITERATE lp 重新執(zhí)行 LOOP 循環(huán),直到循環(huán)結(jié)束。

⑹?REPEAT 語句

? ? 概念:

????含有條件控制的循環(huán)語句,滿足條件跳出循環(huán)

? ? 語法結(jié)構(gòu):

? ??[begin_label:] REPEAT

????statement_list

????UNTIL search_condition?END REPEAT [end_label]

? ? 案例:

? ? 由圖,聲明局部變量 x 循環(huán)加1,大于10時結(jié)束循環(huán)。

⑺?WHILE 語句

? ? 概念:

????含有條件控制的循環(huán)語句,滿足條件進入循環(huán)

? ? 語法結(jié)構(gòu):

? ??[begin_label:] WHILE search_condition DO

????statement_list

????END WHILE [end_label]

? ? 案例:

? ? 由圖,當(dāng) x < 10 時,循環(huán)加1,x >= 10 時跳出循環(huán)。

存儲過程:

MySQL命令的執(zhí)行流程:

如果把流程里的語法分析和編譯的環(huán)節(jié)省略掉,那么 MySQL 的執(zhí)行效率就會提高。所以這就需要存儲過程來完成。

概念:

存儲過程是 SQL 語句和控制語句的預(yù)編譯集合,以一個名詞存儲并作為一個單元處理,它存儲在數(shù)據(jù)庫里面,可以由應(yīng)用程序調(diào)用執(zhí)行,允許用戶聲明變量和進行流程控制,而且可以接收參數(shù),不僅可以接收輸入類型的參數(shù),也可以接收輸出類型的參數(shù),同時可以存在多個返回值。

存儲過程的效率比單一的 SQL 執(zhí)行效率要高,假設(shè)有兩個 SQL 語句,MySQL 引擎會對這個兩個 SQL 語句進行逐一的語法分析,再編譯,再執(zhí)行,而有了存儲過程后,只有第一次才進行語法分析和編譯流程,后續(xù)調(diào)用只需調(diào)用結(jié)果即可。

優(yōu)點:

⑴ 增強 SQL 語句的功能和靈活性

⑵ 實現(xiàn)較快的執(zhí)行速度

如果某個操作包含大量 SQL 語句,那么這些語句都將被 MySQL 引擎進行逐一的語法分析,編譯和執(zhí)行的過程,所以效率相對較低,而存儲過程是預(yù)編譯的,當(dāng)客戶端第一次調(diào)用存儲過程的時候,MySQL 引擎將對它語法分析和編譯等操作,然后把編譯的結(jié)果存儲到內(nèi)存中,后續(xù)調(diào)用直接從內(nèi)存里面調(diào)用結(jié)果。所以效率大量提高。

⑶ 減少網(wǎng)絡(luò)流量

語法結(jié)構(gòu):

CREATE

[ DEFINER = { user | CURRENT_USER } ]

PROCEDURE sp_name ( [ proc_parameter [,...] ] )

[ characteristic ...] routine_body

proc_parameter:

[ IN | OUT | INOUT ] param_name_type

其中,

IN 表示該參數(shù)的值必須在調(diào)用存儲過程時指定

OUT 表示該參數(shù)的值可以被存儲過程改變,并且可以返回

INOUT 表示該參數(shù)的調(diào)用時指定,并且可以被改變和返回

修改存儲過程:

注:只能修改簡單的特性,不能修改過程體,若要修改,只能先把存儲過程刪了,重新創(chuàng)建

語法結(jié)構(gòu):

ALTER PROCEDURE sp_name [characteristic ...]

COMMENT 'string'

| { CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA }

| SQL SECURITY { DEFINER | INVOKER }

COMMENT:注釋

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í)行

過程體:

⑴ 過程體由合法的 SQL 語句構(gòu)成

⑵ 過程體可以是任意的(增、刪、改、查、多表連接)SQL 語句

⑶ 過程體如果為復(fù)合結(jié)構(gòu)則使用 BEGIN ... END 語句

⑷ 復(fù)合結(jié)構(gòu)可以包含聲明,循環(huán),控制結(jié)構(gòu)

調(diào)用存儲過程:

⑴ CALL sp_name ([ parameter [,...]])

⑵ CALL sp_name [()]

刪除存儲過程:

DROP PROCEDURE [IF EXISTS] sp_name

案例:

創(chuàng)建不帶參數(shù)的存儲過程:

存儲體 sp1() 不帶參數(shù),過程體獲取當(dāng)前版本號,調(diào)用該存儲體:

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

查詢下表 tb_goods_cate 的記錄:

再創(chuàng)建一個根據(jù) cate_id 刪除記錄的存儲過程:

注:參數(shù)的變量名不能和表里的字段名一樣

調(diào)用:

刪除 cate_id = 2 的記錄,再查詢下記錄:

cate_id = 2 已刪除。

創(chuàng)建帶有 IN 和 OUT 類型參數(shù)的存儲類型:

由圖,創(chuàng)建存儲過程 test,傳入類目 id,然后查詢對應(yīng)的類目名稱。調(diào)用的時候,傳入 id 等于1,并把返回的名稱賦給全局變量 @name,再通過 SELECT 查詢該變量的值。

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

由圖,創(chuàng)建一個存儲過程 test,傳入類型 id,輸出類型該類型的名稱和表里的記錄總數(shù)。

總結(jié):

⑴ 存儲過程實現(xiàn)的功能比較復(fù)雜,而函數(shù)針對性更強,一般情況下,存儲過程主要針對表做操作

⑵ 存儲過程可以返回多個值,而函數(shù)只能有一個返回值

⑶ 存儲過程一般獨立的來執(zhí)行,而函數(shù)可以作為 SQL 語句中的組成部分

以上為本人的一些學(xué)習(xí)筆記,如有出錯歡迎指正,陸續(xù)更新!!!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,283評論 6 530
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 97,947評論 3 413
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,094評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,485評論 1 308
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 71,268評論 6 405
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 54,817評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 42,906評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,039評論 0 285
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,551評論 1 331
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 40,502評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,662評論 1 366
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,188評論 5 356
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 43,907評論 3 345
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,304評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,563評論 1 281
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,255評論 3 389
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 47,637評論 2 370

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

  • 存儲過程和函數(shù)是事先經(jīng)過編譯并存儲在數(shù)據(jù)庫中的一段 SQL 語句的集合,調(diào)用存儲過程和函數(shù)可以簡化應(yīng)用開發(fā)人員的很...
    微日月閱讀 1,864評論 0 1
  • 2016.1.22編號13 每天晚上躺在床上兒子都要讓我和他一起看書、講故事,這是每天必做的功課,好長...
    f65d0cc1f4f0閱讀 220評論 0 0
  • 一家特殊的假發(fā)店 【一家特殊的假發(fā)店為癌癥患者戴上生命的尊嚴】 “最開始肯定是已盈利為目的,但是做著做著就會想為顧...
    學(xué)生神來啦閱讀 141評論 0 0
  • 2017年12月24日晚5.30左右 圖書館小門 看到了你和你的女朋友 雖然早就已經(jīng)知道 但是眼淚還是不自覺地掉了...
    墨爾本有蒲公英閱讀 253評論 0 0
  • 姑姑今年五十七歲,身材矮小,瘦弱,尤其是一張飽經(jīng)風(fēng)霜的臉,刻滿了皺紋,眼角眉梢枯萎的褶皺,一層一層地揭示著生活的疾...
    玉妮閱讀 2,499評論 23 32