日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

存储程序(1)——MYSQL

發(fā)布時間:2023/12/13 数据库 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 存储程序(1)——MYSQL 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

MySQL支持把幾種對象存放在服務(wù)器端供以后使用。這幾種對象有一些可以根據(jù)情況通過程序代碼調(diào)用,有一些會在數(shù)據(jù)表被修改時自動執(zhí)行,還有一些可以在預(yù)定時刻自動執(zhí)行。它們包括以下幾種:

1.存儲函數(shù)(stored function)。返回一個計算結(jié)果,該結(jié)果可以用在表達式里。
2.存儲過程(stored procedure)。不直接返回一個結(jié)果,但可以用來完成一般的運算或是生成一個結(jié)果集并傳遞回客戶。
3.觸發(fā)器(trigger)。與數(shù)據(jù)表相關(guān)聯(lián),當那個數(shù)據(jù)表被工NSERT、DELETE或UPDATE語句修改時,觸發(fā)器將自動執(zhí)行。
4.事件(event)。根據(jù)時間表在預(yù)定時刻自動執(zhí)行。

MySQL對存儲函數(shù)和存儲過程的支持始于5.0.0版本,對觸發(fā)器和事件的支持分別始于5.0.2版本和5.1.6版本。存儲程序有以下優(yōu)點和能力:

1.存儲程序?qū)ο蟮目蓤?zhí)行部分可以用復(fù)合語句來編寫,復(fù)合語句對SQL語法進行了擴展,可以包括代碼塊、循環(huán)和條件語句。
2.存儲程序都被保存在服務(wù)器端,定義它們所需要的代碼只需在它們被創(chuàng)建時通過網(wǎng)絡(luò)傳遞一次,而不是每次執(zhí)行都要傳遞一次。這大大減少了開銷。
3.它們可以把復(fù)雜的計算封裝為程序單元,而你可以簡單地通過程序單元的名字來調(diào)用它們。你甚至可以把一組存儲程序打包為一個“函數(shù)庫”供其他應(yīng)用程序調(diào)用。
4.它們提供了一種錯誤處理機制。
5.它們可以提高數(shù)據(jù)庫的安全性。你可以通過選擇存儲程序執(zhí)行時所需的權(quán)限下來對敏感數(shù)據(jù)的訪問情況進行限制和調(diào)控。

存儲程序。泛指各種類型的存儲對象(存儲函數(shù)、存儲過程、觸發(fā)器、事件)。存儲例程(stored routine ),特指存儲函數(shù)和存儲過程。這兩種對象的定義語法很相似,所以很自然地把它們放在一起討論。在開始討論各種類型的存儲程序之前,我們首先學(xué)習一下:復(fù)合語句。

1.復(fù)合語句和語句分隔符

簡單的存儲程序只包含一條SQL語句,在編寫時不需要特殊對待。下面的存儲過程使用了一條SELECT語句來列出sampdb數(shù)據(jù)庫里的數(shù)據(jù)表的名字:

PROCEDURE sampdb_tables() SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA=’sampdb’ ORDER BY TABLE_NAME;

不過,存儲程序并非只能包含一條簡單的SQL語句。它們可以包含多條SQL語句,可以使用局部變量、條件語句、循環(huán)和嵌套語句塊等多種語法構(gòu)造。要使用這些構(gòu)造編寫存儲程序,就需要用到復(fù)合語句。復(fù)合語句由BEGIN開頭,END結(jié)束,在它們之間可以寫出任意數(shù)量的語句,這些語句構(gòu)成了一個語句塊。下面的存儲過程將顯示一條歡迎消息,其中有你的用戶名;如果你是一位匿名用戶,用戶名將是“earthing":

CREATE PROCEDURE greetings() BEGIN#77=16 for username+60 for hostname+1 for '@'DECLARE user CHAR(77) CHARACTER SET utf8;SET user = (SELECT CURRENT USER());IF INSTR(user,’@’)>0 THEN#返回字符串在某一個字段的內(nèi)容中的位置, 沒有找到字符串返回0,否則返回位置(從1開始)SET user=SUBSTRING_INDEX(user, '@', 1);END IF;IF user = '' THENSET user='earthling';END IF;SELECT CONCAT('Greetings,',user, '!') AS greeting; END;

在使用復(fù)合語句時,必須考慮和解決這樣一個問題:復(fù)合語句塊里的語句必須以分號(;)彼此隔開,但因為分號同時也是mysql程序默認使用的語句分隔符,所以在使用mysql程序定義存儲程序時會發(fā)生沖突。
解決這個問題的辦法是使用delimiter命令把mysql程序的語句分隔符重定義為另一個字符或字符串,它必須是在存儲例程的定義里沒有出現(xiàn)過的。這樣一來,mysql程序就不會把分號解釋為語句終止符了,它將把整個對象定義作為一條語句傳遞給服務(wù)器。在定義完存儲程序之后,可以把mysql程序的語句終止符重新定義為分號。

use weibo; delimiter $ CREATE PROCEDURE show_times() BEGINSELECT 'Local time is:', CURRENT_TIMESTAMP;SELECT 'UTC time is:', UTC_TIMESTAMP; END$ delimiter ;-- delimiter后空格加分號,將分號設(shè)置為分隔符 CALL show_times();

定義一個存儲過程時把mysql程序的默認分隔符臨時改變?yōu)?,然后在恢復(fù)了mysql程序的默認分隔符之后執(zhí)行了那個存儲過程:

?

分隔符不必非得是$字符,也不必非得是單個的字符:

delimiter EOF

這里的原則是:只要在某個存儲程序內(nèi)部的語句里會用到分號,就應(yīng)該在定義這個存儲程序時臨時改變mysql程序的分隔符。

2.存儲函數(shù)和存儲過程

存儲函數(shù)將向調(diào)用者返回一個計算結(jié)果,這個結(jié)果可以用在表達式里(就像COS()或HEX()這樣的內(nèi)建函數(shù)那樣)。存儲過程需要使用CALL語句來調(diào)用,是一個獨立的操作,不能用在表達式里。使用存儲過程的情況主要有兩種:(1)只需通過運算來實現(xiàn)某種效果或動作而無需返回一個值,(2)運算會返回多個結(jié)果集(函數(shù)做不到這一點)。這只是些指導(dǎo)性建議,不是硬性規(guī)定。
比如說,如果你需要返回兩個或更多的值,就不能使用函數(shù)。但你可以使用一個過程,因為過程支持的參數(shù)類型允許它們的值在過程執(zhí)行期間被設(shè)置,而調(diào)用者可以在過程返回后去訪問那些值。

存儲函數(shù)要用CREATE FUNCTION語句來創(chuàng)建,存儲過程要用CREATE PROCEDURE語句來創(chuàng)建。下面的例子將創(chuàng)建一個函數(shù),該函數(shù)有一個代表著年份的整數(shù)參數(shù)。(為了與數(shù)據(jù)表或數(shù)據(jù)列的名字有所區(qū)別,參數(shù)命名時將使用p_前綴)。

delimiter $ CREATE FUNCTION count_born_in_year(p_year INT) RETURNS INT READS SQL DATA BEGINRETURN (SELECT COUNT(*) FROM president WHERE YEAR(birtb) = p_year); END$ delimiter ;

這個函數(shù)有一條用來表明其返回值數(shù)據(jù)類型的RETURNS子句和一個用來計算那個值的函數(shù)體。函數(shù)體至少需要包含一條RETURN語句,用來向調(diào)用者返回一個值。把計算定義為函數(shù)的好處是可以方便地執(zhí)行它而無須每次都寫出所有的邏輯,你可以像使用內(nèi)建函數(shù)那樣來調(diào)用存儲函數(shù):

SELECT count_born_in_year(1990);

你無法讓一個給定的函數(shù)返回多個值。你可以編寫任意多個函數(shù),然后在同一條語句里調(diào)用它們?nèi)w。另一個辦法是使用一個存儲過程并通過它的OUT參數(shù)“返回”多個值。存儲過程負責計算那些值并把它們賦值給相應(yīng)的參數(shù),而那些參數(shù)可以在過程返回后由調(diào)用者訪問。如果你定義了一個與某個MySQL內(nèi)建函數(shù)同名的存儲函數(shù),在調(diào)用它時就必須用數(shù)據(jù)庫的名字對該函數(shù)的名字進行限定以避免歧義。

存儲過程和存儲函數(shù)很相似,但它不返回值。因此,它沒有RETURNS子句或任何RETURN語句。下面這個簡單的存儲過程和count_born_in_year()函數(shù)很相似,它將顯示一個結(jié)果集而不是把計算結(jié)果作為其返回值。

delimiter $ CREATE PROCEDURE show_born_in_year(p_year INT) BEGINSELECT first_name, last_name, birth, deathFROM presidentWHERE YEAR(birth)=P_year; END$ delimiter ;

與存儲函數(shù)不同,存儲過程不能用在表達式里,它們只能通過CALL語句來調(diào)用。如下所示:

CALL show_born_in_year(1990);

前面的例子都是選取信息,但存儲例程還可以用來修改數(shù)據(jù)表,如下例所示:

delimiter $ CREATE PROCEDURE update_expiration (p_id INT UNSIGNED, p_date DATE) BEGINUPDATE member SET expiration=p_date WHERE member_id=p_id; END$ delimiter ;

存儲函數(shù)必須遵守這樣一條限制:不允許對調(diào)用本函數(shù)的語句正在讀或?qū)懙臄?shù)據(jù)表進行修改。存儲過程通常沒有這個限制,但如果它們是從存儲函數(shù)里被調(diào)用,就需要遵守這條限制。

3.存儲函數(shù)和存儲過程的權(quán)限

存儲函數(shù)和存儲過程屬于數(shù)據(jù)庫。要想創(chuàng)建存儲函數(shù)或存儲過程,必須擁有那個數(shù)據(jù)庫的CREATE ROUTINE權(quán)限。在默認的情況下,當你創(chuàng)建一個存儲例程時,服務(wù)器將自動地把EXECUTE和ALTER ROUTINE權(quán)限授予你(如果你還沒有獲得這些權(quán)限),這樣你才可以執(zhí)行那個例程或刪除它。當你刪除那個例程時,服務(wù)器將自動撤銷那些權(quán)限。如果你不想使用這種自動化的權(quán)限授予/撤銷機制,把automatic_sp_privileges系統(tǒng)變量設(shè)置為0即可。

如果服務(wù)器啟用了二進制日志功能,存儲函數(shù)還需要遵守一些額外的限制條件(不允許創(chuàng)建不確定或是會修改數(shù)據(jù)的存儲函數(shù))以保證二進制日志能夠安全地完成備份和復(fù)制操作。這些限制條件如下:
1.如果log_bin_trust_function_creators系統(tǒng)變量沒有被激活,你就必須具備SUPER權(quán)限才能創(chuàng)建存儲函數(shù)。在此前提下,你創(chuàng)建的每一個函數(shù)都必須是確定的,并且不得修改數(shù)據(jù)。為了表明這一點,需要使用DETERMINISTIC、NO SQL或READS SQL DATA之一來定義存儲函數(shù)。
2.如果log bin_trust_function_creators系統(tǒng)變量已被激活,則沒有任何限制。只有當你可以相信MySQL服務(wù)器上的所有用戶都不會去定義不安全的存儲函數(shù)時,這種設(shè)置才是最適當?shù)摹?/p>

與log_bin_trust_function_creators系統(tǒng)變量有關(guān)的限制條件同樣適用于觸發(fā)器的創(chuàng)建工作。

4.存儲過程的參數(shù)類型

存儲過程的參數(shù)分為3種類型。對于IN參數(shù),調(diào)用者把一個值傳遞給過程,過程可以對這個值進行修改,但任何修改在過程返回后對調(diào)用者是不可見的。OUT參數(shù)剛好相反,過程把一個值賦值給OUT參數(shù),這個值在過程返回后可以由調(diào)用者訪問。INOUT參數(shù)允許調(diào)用者向過程傳遞一個值,然后再取回一個值。
要想明確地為參數(shù)指定類型,在參數(shù)表里把IN, OUT或INOUT寫在參數(shù)名字前面即可。如果沒有為參數(shù)指定類型,其默認類型將是IN。

在使用OUT或INOUT參數(shù)時,在調(diào)用過程時需要給出一個變量名。過程可以設(shè)置參數(shù)的值,相應(yīng)的變量將在過程返回時獲得那個值。如果想讓某個存儲過程返回多個結(jié)果值,OUT和INOUT參數(shù)類型將非常有用(存儲函數(shù)只能返回一個值,不能勝任)。下面的過程演示了OUT參數(shù)的用法。它將分別統(tǒng)計出student數(shù)據(jù)表里的男生和女生人數(shù)并通過它的參數(shù)返回這兩個計數(shù)值,讓調(diào)用者可以訪問它們:

delimiter $ CREATE PROCEDURE count_students_by_sex(OUT p_male INT, OUT p_female INT) BEGINSELECT COUNT(*) FROM student WHERE sex= 'F' INTO p_female;SELECT COUNT(*) FROM student WHERE sex= 'F' INTO p_female; END$ delimiter ;

在調(diào)用這個過程時,請把各個參數(shù)替換為相應(yīng)的用戶定義變量。這個過程將把計數(shù)值放到這些參數(shù)里,在它返回之后,那些變量將包含計數(shù)值:

CALL count_students_by_sex(@mcoant, @fcount); SELECT 'Number of male students:'@mcount;

IN、OUT和INOUT關(guān)鍵字不適用于存儲函數(shù)、觸發(fā)器或事件。對于存儲函數(shù),所有的參數(shù)都像IN參數(shù)。觸發(fā)器和事件則根本沒有任何參數(shù)。下一部分介紹:觸發(fā)器和事件。

轉(zhuǎn)載于:https://www.cnblogs.com/houkai/p/3523563.html

總結(jié)

以上是生活随笔為你收集整理的存储程序(1)——MYSQL的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。