存儲程序(1)——MYSQL

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

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

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

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

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

1.復合語句和語句分隔符

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

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

不過,存儲程序并非只能包含一條簡單的SQL語句。它們可以包含多條SQL語句,可以使用局部變量、條件語句、循環和嵌套語句塊等多種語法構造。要使用這些構造編寫存儲程序,就需要用到復合語句。復合語句由BEGIN開頭,END結束,在它們之間可以寫出任意數量的語句,這些語句構成了一個語句塊。下面的存儲過程將顯示一條歡迎消息,其中有你的用戶名;如果你是一位匿名用戶,用戶名將是“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#返回字符串在某一個字段的內容中的位置, 沒有找到字符串返回0,否則返回位置(從1開始)SET user=SUBSTRING_INDEX(user, '@', 1);END IF;IF user = '' THENSET user='earthling';END IF;SELECT CONCAT('Greetings,',user, '!') AS greeting;
END;

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

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

定義一個存儲過程時把mysql程序的默認分隔符臨時改變為$,然后在恢復了mysql程序的默認分隔符之后執行了那個存儲過程:

Local time is:2014-01-15 23:00:26?
image

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

delimiter EOF

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

2.存儲函數和存儲過程

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

存儲函數要用CREATE FUNCTION語句來創建,存儲過程要用CREATE PROCEDURE語句來創建。下面的例子將創建一個函數,該函數有一個代表著年份的整數參數。(為了與數據表或數據列的名字有所區別,參數命名時將使用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 ;

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

SELECT count_born_in_year(1990);

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

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

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

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

CALL show_born_in_year(1990);

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

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 ;

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

3.存儲函數和存儲過程的權限

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

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

與log_bin_trust_function_creators系統變量有關的限制條件同樣適用于觸發器的創建工作。

4.存儲過程的參數類型

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

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

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 ;

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

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

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

轉載于:https://www.cnblogs.com/houkai/p/3523563.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/260900.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/260900.shtml
英文地址,請注明出處:http://en.pswp.cn/news/260900.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

闖過這 54 關,點亮你的 Git 技能樹 (五) - 完結篇

這是一個系列文章,介紹學習 Git 的一個小游戲 - githug,如果你是第一次看到,請先閱讀:闖過這 54 關,點亮你的 Git 技能樹闖過這 54 關,點亮你的 Git 技能樹(一)闖過這 54 關&#xf…

Jupyter notebook 不安裝主題,通過修改css更改 默認字體,字體大小等

目標: Jupyter notebook 又不想改更主題的的情況下,可以通過修改css的目的來達到修改默認的字體,字號心達到可以好的閱讀效果。 方法 要修改的css文件目錄如下, D:\Anaconda\Lib\site-packages\notebook\static\custom 這個就是…

項亮 陳義 王益《推薦系統實踐》

最近很多讀者關注《推薦系統實踐》一書,詢問本書目前的寫作進展和出版時間。自今日起,本書正式進入開放出版流程,作者會全程在本社區中互動,與大家分享寫做過程中的點滴。 技術背景 推薦系統從1994年開始,經過Amazon&a…

堅果nuts 加速 官網_【喂你播】堅果手機2020新品發布會來了;三星定向華為手機推以舊換新...

周五喂diu 不只有你們愛的女主播 還有小編呢BGM:Make You Hustle-Croatia Squad堅果手機2020新品發布會來了堅果手機正式宣布:堅果手機2020新品發布會將于10月20日19:30在五棵松M空間舉行。根據此前爆料,堅果手機新品或命名為堅果Pro4&#x…

不可不知的Oracle常用技巧

不可不知的Oracle常用技巧 表復制 1.方法一:復制表結構和數據 create table temp_clientloginuser as select distinct userid from tbuserloginlog; 2.方法二:僅復制數據 -- 如果表結構一樣 insert into mytable select * from yourtable; -- 如果表結構…

圖像處理核函數:之高斯核的生成方法 python

圖像處理核函數:之高斯核函數的生成方法 python高斯核函數(低通高斯濾波器核)高斯分布函數高斯核生成函數代碼效果高斯核函數的圖像高斯核函數(低通高斯濾波器核) 最近在看DIP(Digital Image Processing)&…

WEB-INFO/lib build path 的jar包問題

為什么80%的碼農都做不了架構師?>>> 一、build path&WEB-INFO/lib介紹 build path:可以說是引用; WEB-INFO/lib:可以說是固定在一個地方; eclipse編譯項目的時候是根據build path的,如果…

Windows phone 7之頁面布局

Windows phone的頁面布局方式一般是依賴布局控件實現的,而布局控件有三種Grid,StackPanel和Canvas Grid是網格布局方式,相當于一個表格,有行和列,新建一個Windows phone項目,打開MainPage.xaml,…

蘋果電腦刪除軟件_軟件自動開啟很煩人?如何徹底關掉開機自動開啟的應用程序...

使用Mac的小伙伴有沒有這樣的煩惱,電腦一開機,一堆煩人的軟件就自動開啟了,讓人很懊惱,如何才能徹底關掉開機自動開啟的應用程序?mac開機啟動項怎么設置?開機啟動項要怎么禁止?今天就帶大家解決…

UVALive2678子序列

UVALive2678 http://122.207.68.93:9090/csuacmtrain/problem/viewProblem.action?id453 【題目描述】:n個正整數組成的序列。給定整數S,求長度最短的連續序列,使他們的和大于等于S。 【算法分析】: 【二分】: 全是…

Jupyter notebook 使用過程中的一些小技巧總結

Jupyter notebook 小技巧 這是自己使用Jupyter notebook 的過程,遇到的一些問題,還有一些使用的小技巧,希望可以幫且大家。會不定時更新 code 轉 markdown: 按鍵 M code 轉 markdown: 按鍵 Y 換行:打完一…

IOS 文件讀取4種方法 轉字符串 和data

//第一種方法: NSFileManager實例方法讀取數據NSArray* paths NSSearchPathForDirectoriesInDomains(NSDesktopDirectory, NSUserDomainMask, YES);NSString* thepath [paths lastObject];thepath [thepath stringByAppendingPathComponent:"fd_list.txt&qu…

csgo怎么控制電腦玩家_電腦遠程控制怎么弄

本教程以“Win 10”系統為例進行演示。方法一:1/6在“此電腦”單擊鼠標右鍵選擇“屬性”2/6在彈出窗口中點擊“遠程設置”3/6勾選“允許遠程協助連接這臺計算機”,然后點擊應用并確定4/6在微軟小娜搜索“mstsc”5/6打開“遠程桌面連接”6/6輸入對方的IP地…

HTML 5 的自定義 data-* 屬性和jquery的data()方法的使用

HTML 5 的自定義 data-* 屬性和jquery的data()方法的使用 人們總喜歡往HTML標簽上添加自定義屬性來存儲和操作數據。但這樣做的問題是,你不知道將來會不會有其它腳本把你的自定義屬性給重置掉,此外,你這樣做也會導致html語法上不符合Html規范…

java。接口和抽象類區別

接口和抽象類區別 a.抽象類里可以有非抽象方法 接口里只能有抽象方法 b.接口是抽象類的變體,再接口中所有方法都是抽象的轉載于:https://www.cnblogs.com/zhaozhaozhang/p/5759714.html

MNIST 手寫數字識別,我是如何做到886個可訓練參數,識別率達到98.2%? (參數、模型壓縮), Keras實現,模型優化

一 項目展示 下面可以看到驗證集可以到了0.9823了,實際上,在下面的另外一個訓練,可以得到0.9839,我保守的寫了0.982 二 項目參數展示 我們先來看看LeNet 5 的結構與參數,參數有61,706個。 這個是我用…

javascript 計算兩個坐標的距離 米_土方全面應用計算

各種土方量的計算方法匯總8.2.1 DTM法土方計算由DTM模型來計算土方量是根據實地測定的地面點坐標(X,Y,Z)和設計高程,通過生成三角網來計算每一個三棱錐的填挖方量,最后累計得到指定范圍內填方和挖方的土方量,并繪出填…

VS2008 AJAX控件介紹

1 Accordion 2 AccordionPane 實現多面板,每次都只顯示一個,其他收藏起來,可以設置顯示隱藏的時間和漸變效果哦 3 AlwaysVisibleControlExtender 這個東西是將VerticalSide的值設置好后無論頁面的滾動條滾動,這個目標控件一直都顯…

py文件轉exe時包含paramiko模塊出錯解決方法

問題描述:python代碼中包含paramiko模塊的遠程登錄ssh,在用pyInstaller轉為exe時報錯, 報錯提示為“No handlers could be found for logger "paramiko.transport" 出錯位置: ssh paramiko.SSHClient() ssh.set_missin…

unity 陽光插件_網絡廣告,陽光創信保駕護航

網絡廣告 就找陽光創信。網絡營銷的技術基礎主要是以計算機網絡技術為代表的信息技術。計算機網絡是現代通信技術與計算機技術相結合的產物,它把分布在不同地理區域的計算機與專門的外部設備用通信線路互連成一個規模大、功能強的網絡,從而使眾多的計算機…