MySQL數(shù)據(jù)庫教程課件_第1頁
MySQL數(shù)據(jù)庫教程課件_第2頁
MySQL數(shù)據(jù)庫教程課件_第3頁
MySQL數(shù)據(jù)庫教程課件_第4頁
MySQL數(shù)據(jù)庫教程課件_第5頁
已閱讀5頁,還剩98頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)

文檔簡介

第8章MySQL編程技術(shù)命令語句,采用的是聯(lián)機(jī)交互的方式,執(zhí)行的方式是每次一條。為了提高工作效率,可以將多條命令組合在一起,形成一個程序一次性執(zhí)行。因?yàn)槌绦蚴强梢灾貜?fù)使用的,能減少數(shù)據(jù)庫開發(fā)人員的工作量,也能通過設(shè)定程序的權(quán)限來限制用戶對程序的定義和使用,從而提高系統(tǒng)的安全性,MySQL中這樣的程序稱為過程式對象?!緦W(xué)習(xí)目標(biāo)】理解常量和變量的概念。掌握系統(tǒng)內(nèi)置的常用函數(shù)和流程控制語句。能夠編寫簡單的存儲過程。能夠編寫簡單的存儲函數(shù)。能夠編寫簡單的觸發(fā)器代碼。8.1編程基礎(chǔ)知識8.1編程基礎(chǔ)知識8.1.1常量和變量1.常量常量是指在程序中可以直接引用的量,其值在程序運(yùn)行期間保持不變,它的表示形式?jīng)Q定了其數(shù)據(jù)類型。常量可分為數(shù)值常量、字符串常量、日期時間常量、布爾常量和NULL值常量等。(1)數(shù)值常量數(shù)值常量由數(shù)字組成,可以分成整數(shù)常量和實(shí)數(shù)常量。①

整數(shù)常量是不帶小數(shù)點(diǎn)的十進(jìn)制整數(shù)。如156、-100。②

實(shí)數(shù)常量是包含小數(shù)點(diǎn)的數(shù)值常量。如3.14、-100.23、2.67E5(2)字符串常量字符串常量是用單引號或雙引號括起來的字符序列,如″HELLO″、″數(shù)據(jù)庫系統(tǒng)″。(3)日期和時間常量日期常量是用單引號或雙引號括起來的,包括年、月、日,并按照“年-月-日”的順序表示日期,中間的分隔符也可以使用“/”“@”“%”等特殊符號。如“2022-1-1”“2022/1/1”“2022@1@1”“2022%1%1”。時間常量包括時、分、秒、微秒,并按照“時:分:秒:微秒”的順序構(gòu)成,如“10:20:35:45”。(4)布爾常量布爾常量只有TURE和FALSE兩個值。TURE對應(yīng)的數(shù)值為“1”;FALSE對應(yīng)的數(shù)值為“0”。(5)NULL值NULL值適用于各種類型,表示沒有值或無數(shù)據(jù),不等價于空字符串或數(shù)據(jù)0值。2.變量變量是指在程序運(yùn)行期間取值可以變化的量,用于臨時存儲數(shù)據(jù),變量中的數(shù)據(jù)隨著程序的運(yùn)行而變化。一個變量有2個基本要素:變量名和變量的數(shù)據(jù)類型。每個變量都用唯一的變量名來標(biāo)識,用戶可以通過變量名來訪問內(nèi)存中的數(shù)據(jù),變量的數(shù)據(jù)類型決定了變量的值和對應(yīng)的運(yùn)算。MySQL變量可分為用戶變量、系統(tǒng)變量和局部變量。(1)用戶變量用戶使用變量定義語句定義的變量稱為用戶變量。用戶變量與連接有關(guān),一個客戶端定義的變量不能被其他客戶端看到或使用。當(dāng)客戶端退出時,該客戶端連接的所有用戶變量將自動釋放。①SET語句用戶變量在使用前必須定義和初始化,使用SET語句定義和初始化用戶變量的語法格式:SET@用戶變量1=表達(dá)式1[,@用戶變量2=表達(dá)式2

];說明:在用戶變量前添加@符號,便于區(qū)分變量名和字段名稱。用戶變量名可以包含字母、數(shù)字、“.”“_”和“$”。定義多個用戶變量時,每個用戶變量之間用逗號分隔。表達(dá)式是賦給用戶變量的值,可以是常量、變量或表達(dá)式?!纠?-1】使用用戶變量查詢“李華”同學(xué)所在的院系名稱。第一步:在學(xué)生表student中查詢到“李華”同學(xué)所在的院系代碼deptno字段,并存儲在用戶變量@deptno中。mysql>SET@deptno=(SELECTdeptnoFROMstudentWHEREsname="李華");顯示用戶變量@deptno的值。mysql>SELECT@deptno;+---------+|@deptno|+---------+|104|+---------+第二步:在院系表department中查詢等于用戶變量@deptno的院系代碼deptno字段和院系名稱deptname字段。最終查詢到“李華”院系名稱是“電氣與電子工程學(xué)院”。mysql>SELECTdeptno,deptnameFROMdepartmentWHEREdeptno=@deptno;+--------+--------------------+|deptno|deptname|+--------+--------------------+|104|電氣與電子工程學(xué)院|+--------+--------------------+②SELECT

INTO語句SELECT

INTO語句可以將查詢得到的一行結(jié)果中的字段值賦值給對應(yīng)的用戶變量語法格式:SELECT字段1[,字段2

]INTO@用戶變量1[,@用戶變量2

]FROM表名WHERE條件;【例8-2】將學(xué)號sno為“120211040101”的姓名sname和入學(xué)總分enterscore存入用戶變量@name和@score中。定義用戶變量。mysql>SET@name=NULL,@score=NULL;將查詢結(jié)果賦值給用戶變量。mysql>SELECTsname,enterscoreINTO@name,@score->FROMstudent->WHEREsno="120211040101";顯示用戶變量@name和@score的值。mysql>SELECT@name,@score;+--------+--------+|@name|@score|+--------+--------+|王曉紅|630|+--------+--------+(2)系統(tǒng)變量系統(tǒng)變量是MySQL的一些特殊設(shè)置,當(dāng)MySQL數(shù)據(jù)庫服務(wù)器啟動時,初始化這些變量為默認(rèn)值。大多數(shù)系統(tǒng)變量名稱前都需要加兩個@,某些特定的系統(tǒng)變量不加這兩個@,如CURRENT_DATE(當(dāng)前系統(tǒng)日期)、CURRENT_TIME(當(dāng)前系統(tǒng)時間)、CURRENT_USER(當(dāng)前用戶名稱)等?!纠?-3】查看當(dāng)前系統(tǒng)日期和使用的MySQL的版本信息。mysql>SELECTCURRENT_DATEAS當(dāng)前日期,@@versionAS當(dāng)前版本;+------------+----------+|當(dāng)前日期|當(dāng)前版本|+------------+----------+|2022-05-30|8.0.30|+------------+----------+(3)局部變量局部變量的作用范圍是BEGIN

END語句塊中,用來存放存儲過程體中的臨時結(jié)果。局部變量只能定義在存儲過程、存儲函數(shù)和觸發(fā)器中。局部變量和用戶變量的主要區(qū)別:作用范圍不同,用戶變量存在于整個會話中,局部變量只存在于BEGIN

END語句塊中。用戶變量前有@符號,局部變量前沒有@符號。例如,在存儲過程中,聲明局部變量vscore和n,數(shù)據(jù)類型為INT;聲明局部變量vstr和vname,數(shù)據(jù)類型為CHAR。DECLAREvscore,nINT;DECLAREvstr,vnameCHAR;②

局部變量賦值可以使用SET語句或SELECT

INTO語句為局部變量賦值。例如,使用SET語句為局部變量n和vstr賦值。SETn=86,vstr=”good”;例如,使用SELECT

INTO語句為局部變量vname和vscore賦值。SELECTsname,enterscoreINTOvname,vscoreFROMstudentWHEREsno="120211040101";8.1.2系統(tǒng)內(nèi)置函數(shù)在MySQL中提供了許多內(nèi)置的標(biāo)準(zhǔn)函數(shù),每個標(biāo)準(zhǔn)函數(shù)可以實(shí)現(xiàn)某個特定的功能,方便用戶使用。函數(shù)的調(diào)用格式如下。函數(shù)名([參數(shù)1[,參數(shù)2

]])說明:(1)參數(shù)可以是常量、變量或表達(dá)式。(2)函數(shù)可以沒有參數(shù),也可以有一個或多個參數(shù),多個參數(shù)之間用逗號進(jìn)行分隔。

(3)調(diào)用函數(shù)后,得到一個函數(shù)的返回值。函數(shù)名和括號之間不能有空格;沒有參數(shù)的函數(shù)也不能省略括號()。1.?dāng)?shù)學(xué)函數(shù)數(shù)學(xué)函數(shù)完成數(shù)學(xué)計算功能函數(shù)函數(shù)功能示例返回結(jié)果ABS(n)返回數(shù)值表達(dá)式n的絕對值A(chǔ)BS(-2.5)2.5ROUND(n,m)返回按照指定的小數(shù)位數(shù)m對n值四舍五入的結(jié)果ROUND(12.38,1)12.4TRUNCATE(n,m)返回按照指定的小數(shù)位數(shù)m對n值截取的結(jié)果TRUNCATE(12.38,1)12.3SQRT(n)返回數(shù)值表達(dá)式的平方根SQRT(9)3【例8-4】統(tǒng)計學(xué)生表student中男女生入學(xué)總分的平均值(保留2位小數(shù))。mysql>SELECTsexAS性別,ROUND(AVG(enterscore),2)AS平均值

->FROMstudent

->GROUPBYsex;+------+--------+|性別|平均值|+------+--------+|男|640.38||女|613.43|+------+--------+2.字符串函數(shù)字符串函數(shù)用來處理字符串型變量或字符串表達(dá)式。函數(shù)函數(shù)功能示例返回結(jié)果ASCII(c)返回字符串c最左邊字符的ASCII碼ASCII("A")65CHAR(n)將數(shù)值n轉(zhuǎn)換成字符CHAR(65)ACONCAT(c1,c2

)將多個字符串進(jìn)行連接CONCAT("AB","XYZ")"ABXYZ"LENGTH(c)求字符串c的長度LENGTH("ABCD")4LEFT(c,n)取字符串c左邊的n個字符LEFT("ABCD",3)"ABC"RIGHT(c,n)取字符串c右邊的n個字符RIGHT("ABCD",3)"BCD"SUBSTRING(c,n1[,n2])取子字符串,在c串中從n1位置開始取n2個字符。缺省n2時,從n1位置開始取到串尾SUBSTRING(“ABCDE”,2,3)"BCD"REPLACE(c1,c2,c3)用字符串c3替換c1中出現(xiàn)的所有字符串c2,返回替換后的字符串。REPLACE("ABCDABE","AB","12")"12CD12E"LTRIM(c)去掉字符串c中左邊的空格LTRIM("ABCD")"ABCD"RTRIM(c)去掉字符串c中右邊的空格RTRIM("ABCD")"ABCD"TRIM(c)去掉字符串c中左右兩邊的空格TRIM("ABCD")"ABCD"LOWER(c)將字符串c轉(zhuǎn)換為小寫字符LOWER(("AB")“ab”UPPER(c)將字符串c轉(zhuǎn)換為大寫字符UPPER(“ab”)“AB”【例8-5】查詢學(xué)生表student中姓“李”的學(xué)號sno、姓名sname、性別sex和入學(xué)總分enterscore。mysql>SELECTsno,sname,sex,enterscoreFROMstudent

->WHERELEFT(sname,1)="李";+--------------+--------+------+------------+|sno|sname|sex|enterscore|+--------------+--------+------+------------+|120211010230|李媛媛|女|596||120211040108|李明|男|650||120211041102|李華|女|648||120211070101|李淑子|女|589|+--------------+--------+------+------------+【例8-6】將教師表teacher中姓名tname字段分成姓和名字兩列顯示。mysql>SELECTLEFT(tname,1)AS姓,SUBSTRING(tname,2,LENGTH(tname)-1)AS名字->FROMteacher;+------+------+|姓|名字|+------+------+|周|家羅||孟|凱彥||宋|江科||朱|軍||李|亞明||楊|麗||林|達(dá)||王|平||趙|曉麗||馬|麗|+------+------+3.日期和時間函數(shù)日期和時間函數(shù)用于處理日期和時間型表達(dá)式或變量函數(shù)函數(shù)功能示例返回結(jié)果CURDATE()返回系統(tǒng)當(dāng)前日期CURDATE()2022-8-12CURTIME()返回系統(tǒng)當(dāng)前時間CURTIME()11:23:58NOW()返回系統(tǒng)當(dāng)前日期和時間NOW()2022-8-1211:23:58YEAR(d)返回日期表達(dá)式d的年份YEAR("2022-8-12")2022MONTH(d)返回日期表達(dá)式d的月份MONTH("2022-8-12")8DAY(d)返回日期表達(dá)式d的天數(shù)DAY("2022-8-12")12DATEDIFF(d1,d2)返回兩個日期之間的天數(shù)DATEDIFF("2022-8-16","2022-8-10")6【例8-7】查詢學(xué)生表student中學(xué)生的年齡。“年齡”通過計算表達(dá)式“YEAR(NOW())-YEAR(birthdate)”獲得,使用AS指定列標(biāo)題為“年齡”。mysql>SELECTsnoAS學(xué)號,snameAS姓名,YEAR(NOW())-YEAR(birthdate)AS年齡->FROMstudent;+--------------+--------+------+|學(xué)號|姓名|年齡|+--------------+--------+------+|120211010103|宋洪博|19||120211010105|劉向志|20||120211010230|李媛媛|19||120211030110|王琦|19||120211030409|張虎|19||120211040101|王曉紅|20||120211040108|李明|20||120211041102|李華|19||120211041129|侯明斌|20||120211050101|張函|19||120211050102|唐明卿|20||120211060104|王剛|18||120211060206|趙壯|19||120211070101|李淑子|19||120211070106|劉麗|20|+--------------+--------+------+TRUNCATE(DATEDIFF(NOW(),birthdate)/365,0)4.其他函數(shù)函

數(shù)函

數(shù)

能示

例返回結(jié)果IF(expr,v1,v2)判斷條件表達(dá)式expr的值,如果為真則返回v1的值;否則返回v2的值IF(5>0,’是’,’否’)是IFNULL(v1,v2)如果v1的值不為空則返回v1的值;否則返回v2的值IFNULL(5,2)5VERSION()返回當(dāng)前數(shù)據(jù)庫的版本號VERSION()8.0.30【例8-8】判斷5*2是否大于3*3,如果是,則返回“是”,否則返回“否”。mysql>SELECTIF(5*2>3*3,'是','否');+-----------------------+|IF(5*2>3*3,'是','否')|+-----------------------+|是|+-----------------------+8.1.3流程控制語句程序是按照一定的結(jié)構(gòu)來控制整個流程的,流程控制語句是用來控制程序執(zhí)行順序的語句MySQL的流程控制語句和局部變量一樣只能放在存儲過程、存儲函數(shù)或觸發(fā)器中來控制程序的執(zhí)行流程,不能單獨(dú)執(zhí)行流程控制語句有:順序語句分支語句循環(huán)語句1.順序語句(1)BEGIN

END語句塊。使用BEGIN

END定義語句塊,語句塊中可以包含一組語句,語句可以嵌套。關(guān)鍵字BEGIN定義語句的起始位置,END定義同一語句塊的結(jié)束位置。語法結(jié)構(gòu):BEGIN語句序列;END例如:BEGINSELECTsno,sname,sexFROMstudent;END;(2)DELIMITER命令在BEGIN

END語句塊中可能包含多個SQL語句,SQL語句是以分號為結(jié)束標(biāo)志。MySQL服務(wù)器處理程序時,分號是默認(rèn)的結(jié)束標(biāo)志。系統(tǒng)處理到第一個分號時就認(rèn)為程序結(jié)束了,導(dǎo)致后序的SQL語句不能執(zhí)行,此時需要使用DELIMITER命令將MySQL語句的結(jié)束標(biāo)志修改為其他符號,這樣就可以連續(xù)執(zhí)行多個SQL語句了語法結(jié)構(gòu):DELIMITER結(jié)束符用戶可以使用“$$”“##”等特殊的符號為結(jié)束符,注意避免使用MySQL中的轉(zhuǎn)義字符“\”。例如,將MySQL語句的結(jié)束標(biāo)志修改為“$$”。可以使用如下語句。DELIMITER$$這條語句執(zhí)行后,結(jié)束符就變成了“$$”,接下來的語句必須使用“$$”結(jié)束。例如,SELECTsno,sname,sexFROMstudentWHEREsex=”男”$$DELIMITER$$BEGINSELECTsno,sname,sexFROMstudentWHEREsex=”男”;SELECTsno,sname,sexFROMstudentWHEREsex=”女”;END$$DELIMITER;如果想恢復(fù)使用分號“;”作為結(jié)束符,則需要執(zhí)行如下的語句。DELIMITER;2.分支語句(1)IF語句IF-THEN-ELSE語句可以根據(jù)不同的條件執(zhí)行不同的操作語法格式:IF條件1THEN語句序列1[ELSEIF條件2THEN語句序列2]

[ELSE語句序列n]ENDIF;IF語句執(zhí)行流程先計算條件的值。當(dāng)某個條件值為真(TRUE)時,則執(zhí)行相應(yīng)的語句序列;如果沒有一個條件值為真,則執(zhí)行ELSE中的語句序列n?!纠?-9】查詢課程表course中“數(shù)據(jù)庫應(yīng)用”課程的學(xué)時數(shù)hours,如果查詢結(jié)果為空,則顯示“無學(xué)時數(shù)信息”,否則顯示學(xué)時數(shù)。DECLAREvhoursINT;SELECThoursINTOvhoursFROMcourseWHEREcname=”數(shù)據(jù)庫應(yīng)用”IFvhoursISNULLTHENSELECT“無學(xué)時數(shù)信息”AS學(xué)時數(shù);ELSESELECTvhoursAS學(xué)時數(shù);ENDIF;(2)CASE語句CASE是另一種分支語句,有兩種語法格式。CASE語句格式一:CASE表達(dá)式WHEN值1THEN語句序列1[WHEN值2THEN語句序列2]

[ELSE語句序列n]ENDCASE;CASE語句格式一執(zhí)行流程如下。先計算出表達(dá)式的值然后與WHEN

THEN語句塊中的值進(jìn)行比較如果某個值比較的結(jié)果為真,則執(zhí)行對應(yīng)語句序列中的語句如果每一個語句塊中的值都不匹配,則執(zhí)行ELSE語句序列n中的語句CASE語句格式二如下。CASEWHEN條件1THEN語句序列1[WHEN條件2THEN語句序列2]

[ELSE語句序列n]ENDCASE;CASE語句格式二執(zhí)行流程如下。CASE關(guān)鍵字后沒有參數(shù)。在WHEN

THEN語句塊中指定一個條件如果條件的結(jié)果為真時,則執(zhí)行對應(yīng)語句序列中的語句如果每一個語句塊中的條件表達(dá)式均不為真,則執(zhí)行ELSE語句序列n中的語句【例8-10】查詢學(xué)生表student中“劉向志”所屬的級存入變量中。班級classno字段中的第3、4位表示是級的信息。例如,“電氣2101班”對應(yīng)的級為“2021級”。DECLAREvclassCHAR(2);DECLAREvclassyearCHAR(5);SELECTSUBSTRING(classno,3,2)INTOvclassFROMstudentWHEREsname=”劉向志”;CASEvclassWHEN“21”THENSETvclassyear=”2021級”WHEN“20”THENSETvclassyear=”2020級”WHEN“19”THENSETvclassyear=”2019級”WHEN“18”THENSETvclassyear=”2018級”ENDCASE;3.循環(huán)語句循環(huán)語句有三種形式,分別為:

WHILE語句REPEAT語句LOOP語句(1)WHILE語句語法格式:WHILE條件DO

語句序列ENDWHILE;WHILE語句執(zhí)行流程如下。首先判斷條件是否成立如果條件成立,則執(zhí)行語句序列然后再次判斷條件是否成立,如果條件成立則繼續(xù)循環(huán),否則結(jié)束循環(huán)?!纠?-11】計算1+2+3+

+100的和。DECLAREnINTDEFAULT1;DECLAREsumINTDEFAULT0;WHILEn<=100DOSETsum=sum+n;SETn=n+1;ENDWHILE;

變量

sum必須使用DEFAULT0

賦初值為0,否則其初值默認(rèn)為NULL,最終得到的結(jié)果為NULL,不能得到正確的結(jié)果。(2)REPEAT語句語法格式如下。REPEAT語句序列UNTIL條件ENDREPEAT;REPEAT語句執(zhí)行流程如下。首先執(zhí)行語句序列,然后判斷條件是否成立,如果條件不成立則繼續(xù)循環(huán),否則結(jié)束循環(huán)。REPEAT語句是“先執(zhí)行,后判斷”,循環(huán)體至少被執(zhí)行一次;而WHILE語句是“先判斷,后執(zhí)行”,循環(huán)體可能一次也不被執(zhí)行?!纠?-12】計算2+4+6+

+100的和。DECLAREnINTDEFAULT2;DECLAREsumINTDEFAULT0;REPEATSETsum=sum+n;SETn=n+2;UNTILn>100ENDREPEAT;(3)LOOP語句語法格式為:[語句標(biāo)號:]LOOP語句序列ENDLOOP[語句標(biāo)號];LOOP語句執(zhí)行流程如下。重復(fù)執(zhí)行語句序列,語句序列中通常存在一個LEAVE語句,執(zhí)行到該語句時退出循環(huán)。其中的語句標(biāo)號是用戶自定義的名稱。①

退出循環(huán)語句LEAVE的語法格式如下。LEAVE語句標(biāo)號;其中,語句標(biāo)號是LOOP語句中自定義的名稱。執(zhí)行到該語句時結(jié)束循環(huán)。②

再次循環(huán)語句ITERATE的語法格式如下。ITERATE語句標(biāo)號;ITERATE語句只能出現(xiàn)在WHILE、REPEAT和LOOP語句中,結(jié)束本次的循環(huán),然后開始下一次的循環(huán)。【例8-13】計算5的階乘。DECLAREn,fINTDEFAULT1;label1:LOOPSETf=f*n;SETn=n+1;IFn>5THENLEAVElabel1;ENDIF;ENDLOOPlabel1;8.2存儲過程存儲過程是在數(shù)據(jù)庫中定義的SQL語句的集合,經(jīng)過編譯后存儲在數(shù)據(jù)庫中,用戶通過指定存儲過程的名稱并給出需要的參數(shù)來調(diào)用執(zhí)行存儲過程中的語句。用戶可以將經(jīng)常需要執(zhí)行的特定操作寫成存儲過程,每次需要時調(diào)用該存儲過程,可以實(shí)現(xiàn)一個存儲過程的多次調(diào)用,實(shí)現(xiàn)了程序的模塊化設(shè)計。因?yàn)榇鎯^程是預(yù)編譯的,可以加快執(zhí)行速度。存儲過程由聲明式SQL語句(如SELECT、INSERT、UPDATE等語句)和過程式SQL語句(如IF-THEN-ELSE等流程控制語句)組成,完成對較為復(fù)雜問題的處理。8.2.1創(chuàng)建存儲過程使用CREATEPROCEDURE語句可以創(chuàng)建存儲過程語法格式:CREATEPROCEDURE存儲過程名([參數(shù)1[,參數(shù)2

]])[特征]存儲過程體

說明

(1)存儲過程名:用戶自定義的存儲過程名稱。(2)參數(shù):存儲過程中的參數(shù)是形式參數(shù),簡稱形參

調(diào)用存儲過程使用的參數(shù)是實(shí)際參數(shù),簡稱實(shí)參。

形式參數(shù)有輸入?yún)?shù)IN、輸出參數(shù)OUT、輸入輸出參數(shù)INOUT共3種參數(shù)。

形式為:[IN

OUT

INOUT]參數(shù)名類型。

IN:將實(shí)參的值傳遞給形參,作為存儲過程的輸入值。

OUT:是存儲過程的輸出值,結(jié)束時將形參的結(jié)果值傳遞給實(shí)參。

INOUT:既是輸入值也是輸出值,調(diào)用存儲過程時將實(shí)參傳遞給形參,存儲過程結(jié)束后將形參傳遞給實(shí)參。存儲過程可以有0個或多個參數(shù),沒有參數(shù)時存儲過程名后的括號()必須保留;當(dāng)有多個參數(shù)時,各個參數(shù)之間用逗號分隔。(3)存儲過程體:調(diào)用存儲過程時將要執(zhí)行的SQL語句,這部分總是以BEGIN開始,END為結(jié)束。當(dāng)存儲過程體中只有一條SQL語句時,可以省略BEGIN

END語句。(4)特征的格式如下。

LANGUAGESQL

[NOT]DETERMINISTIC

{CONTAINSSQL

NOSQL

READSSQLDATA

MODIFIESSQLDATA}

SQLSECURITY{DEFINER

INVOKER}

COMMENT‘STRING’①LANGUAGESQL:說明存儲過程體部分由SQL語句組成。②[NOT]DETERMINISTIC:指明存儲過程的執(zhí)行結(jié)果是否是確定的。DETERMINISTIC表示結(jié)果是確定的,不同用戶輸入相同的數(shù)據(jù)會得到相同的輸出結(jié)果。NOTDETERMINISTIC表示結(jié)果是非確定的,不同用戶輸入相同的數(shù)據(jù)可能會得到不同的輸出結(jié)果。③{CONTAINSSQL

NOSQL

READSSQLDATA

MODIFIESSQLDATA}:指明子程序使用SQL語句的限制。CONTAINSSQL表示子程序中包含SQL語句,但不包含讀或?qū)憯?shù)據(jù)的語句;NOSQL表示子程序中不包含SQL語句;READSSQLDATA表示子程序中包含讀數(shù)據(jù)的語句;MODIFIESSQLDATA表示子程序中包含寫數(shù)據(jù)的語句;CONTAINSSQL是默認(rèn)值。④SQLSECURITY{DEFINER

INVOKER}:指明執(zhí)行的權(quán)限。DEFINER表示只有定義者才能執(zhí)行,是默認(rèn)值;INVOKER表示調(diào)用者可以執(zhí)行。⑤COMMENT‘STRING’:注釋信息,用來描述存儲過程的功能。8.2.2調(diào)用存儲過程創(chuàng)建存儲過程后,可以在程序、觸發(fā)器、其他存儲過程中使用CALL語句調(diào)用。其語法格式如下。CALL存儲過程名([參數(shù)1[,參數(shù)2

]]);說明:(1)參數(shù)是調(diào)用存儲過程使用的實(shí)在參數(shù),簡稱實(shí)參。(2)實(shí)參的個數(shù)必須與存儲過程定義的形參個數(shù)相同?!纠?-14】創(chuàng)建無參數(shù)的存儲過程p_count,實(shí)現(xiàn)統(tǒng)計學(xué)生表student中的學(xué)生人數(shù)。創(chuàng)建存儲過程。CREATEPROCEDUREp_count()SELECTCOUNT(sno)AS學(xué)生人數(shù)FROMstudent;調(diào)用這個存儲過程。mysql>CALLp_count();+----------+|學(xué)生人數(shù)|+----------+|15|+----------+【例8-15】創(chuàng)建帶輸入?yún)?shù)的存儲過程p_countsex,實(shí)現(xiàn)統(tǒng)計學(xué)生表student中指定性別的學(xué)生人數(shù)。創(chuàng)建存儲過程,該存儲過程包含了一個輸入?yún)?shù)。CREATEPROCEDUREp_countsex(INvsexCHAR(1))SELECTCount(sno)AS人數(shù)FROMstudentWHEREsex=vsex;調(diào)用這個存儲過程,將實(shí)參“女”傳遞給形參vsex。CALLp_countsex(“女”);+----------+|人數(shù)|+----------+|7|+----------+【例8-16】創(chuàng)建帶輸入和輸出參數(shù)的存儲過程p_avggrade,實(shí)現(xiàn)統(tǒng)計某門課程的平均成績是否達(dá)到預(yù)期效果,如果大于等于80,則顯示“該課程成績達(dá)到預(yù)期效果”,否則顯示“該課程成績沒有達(dá)到預(yù)期效果”。DELIMITER$$CREATEPROCEDUREp_avggrade(INvcnameCHAR(50),OUTevaluateCHAR(50))BEGINDECLAREvavgFLOAT;SELECTAVG(grade)INTOvavgFROMcourseJOINscoreONo=oJOINstudentONstudent.sno=score.snoWHEREcname=vcname;IFvavg>=80THENSETevaluate="該課程成績達(dá)到預(yù)期效果";ELSESETevaluate="該課程成績沒有達(dá)到預(yù)期效果";ENDIF;END$$DELIMITER;因?yàn)槠渲杏卸鄺l語句,需要先用DELIMITER語句將語句的結(jié)束標(biāo)識轉(zhuǎn)換為“$$”,然后在BEGIN和END之間編寫存儲過程體,最后用DELIMITER語句將語句的結(jié)束標(biāo)識恢復(fù)為分號“;”。在MySQL命令行創(chuàng)建存儲過程。調(diào)用這個存儲過程時使用用戶變量@eval作為實(shí)參得到輸出的結(jié)果,實(shí)參必須是用戶變量才能查詢到結(jié)果,如果定義為局部變量,存儲過程執(zhí)行后,不能查詢到該局部變量的結(jié)果。調(diào)用該存儲過程統(tǒng)計“數(shù)據(jù)庫應(yīng)用”的平均成績,在MySQL命令行輸入如下命令語句,執(zhí)行結(jié)果如下。mysql>CALLp_avggrade(“數(shù)據(jù)庫應(yīng)用”,@eval);該存儲過程的輸出結(jié)果保存在用戶變量@eval中,通過SELECT語句查看結(jié)果。mysql>SELECT@eval;顯示用戶變量@eval的結(jié)果如下。+------------------------+|@eval|+------------------------+|該課程成績達(dá)到預(yù)期效果|+------------------------+8.2.3刪除存儲過程當(dāng)存儲過程不再需要時,為了釋放其所占用的存儲空間,可以使用DROPPROCEDURE語句刪除。語法格式:DROPPROCEDURE[IFEXISTS]存儲過程名;說明:(1)存儲過程名:需要刪除的存儲過程名稱。(2)IFEXISTS:可選項(xiàng),檢測指定的存儲過程名是否存在,存在時才執(zhí)行刪除??梢员苊庥捎诖鎯^程名不存在而引起的錯誤。【例8-17】刪除存儲過程p-count。mysql>DROPPROCEDUREp_count;8.2.4使用游標(biāo)游標(biāo)能從結(jié)果集中每次提取一條記錄進(jìn)行處理,游標(biāo)類似指針,一次指向一條記錄行,能夠遍歷結(jié)果集的全部記錄。游標(biāo)不能單獨(dú)在查詢中使用,一定要在存儲過程或存儲函數(shù)中使用。1.聲明游標(biāo)使用游標(biāo)之前首先要聲明游標(biāo),定義SELECT語句的結(jié)果集語法格式:DECLARE游標(biāo)名CURSORFORSELECT語句;

說明

(1)使用SELECT語句查詢出來的結(jié)果構(gòu)成結(jié)果集。(2)游標(biāo)聲明時,定義的SELECT語句還沒有執(zhí)行,沒有結(jié)果集。因此聲明游標(biāo)之后必須打開游標(biāo)。2.打開游標(biāo)打開游標(biāo)即執(zhí)行與之對應(yīng)的SELECT語句,得到結(jié)果集語法格式:OPEN游標(biāo)名;3.提取數(shù)據(jù)提取數(shù)據(jù)可以獲取游標(biāo)所指向的結(jié)果集中的當(dāng)前記錄,并將各個字段值傳送給一組對應(yīng)的變量。變量的個數(shù)必須與SELECT語句返回的字段個數(shù)一致語法格式:FETCH游標(biāo)名INTO變量列表;

說明

(1)FETCH語句每次執(zhí)行只能從結(jié)果集中提取一條記錄。(2)如果需要逐條提取全部結(jié)果集中的記錄,必須將FETCH語句放置在循環(huán)語句中。4.關(guān)閉游標(biāo)游標(biāo)使用結(jié)束后需要及時關(guān)閉,這樣可以釋放游標(biāo)所占用的內(nèi)存空間語法格式:CLOSE游標(biāo)名;5.游標(biāo)錯誤處理程序使用FETCH語句提取結(jié)果集中的最后一條記錄后,再執(zhí)行FETCH語句會產(chǎn)生錯誤,其提示信息為“ERROR1329(02000):nodatatoFETCH”,所以需要游標(biāo)錯誤處理程序語法格式:DECLARE錯誤處理類型HANDLEFORNOTFOUND錯誤處理程序;

說明

(1)錯誤處理程序:表示發(fā)生錯誤后,MySQL會立即執(zhí)行錯誤處理程序中的SQL語句。(2)錯誤處理類型:類型值為CONTINUE和EXIT。CONTINUE表示錯誤發(fā)生后,MySQL會立即執(zhí)行錯誤處理程序,然后忽略該錯誤繼續(xù)執(zhí)行其他MySQL語句。EXIT表示錯誤發(fā)生后,MySQL會立即執(zhí)行錯誤處理程序,并且立刻停止執(zhí)行其他MySQL語句。聲明游標(biāo)打開游標(biāo)提取數(shù)據(jù)是最后一條記錄嗎?關(guān)閉游標(biāo)是否計算數(shù)據(jù)開始結(jié)束游標(biāo)的流程示意圖【例8-18】創(chuàng)建一個包含游標(biāo)的存儲過程p_award,根據(jù)入學(xué)總分顯示獎勵的等級,680分及以上顯示“特等獎”,660~679顯示“優(yōu)秀獎”,其他分?jǐn)?shù)段不顯示,最后顯示“特等獎”和“優(yōu)秀獎”的人數(shù)。

分析:可以用游標(biāo)取得包含學(xué)號sno,、姓名sname,、入學(xué)總分enterscore這3個字段的結(jié)果集,然后逐一從結(jié)果集中取出當(dāng)前記錄的3個字段值存入對應(yīng)的3個變量中,用條件判斷語句按照設(shè)定的條件執(zhí)行不同的操作,并分別累加獲獎學(xué)生人數(shù),結(jié)果集中的記錄全部取出后,顯示最終的“特等獎”和“優(yōu)秀獎”的人數(shù)。DELIMITER$$CREATEPROCEDUREp_award()BEGINDECLAREdoneINTDEFAULT0;DECLAREvnoCHAR(12);DECLAREvname,vawardCHAR(50);DECLAREvscore,n1,n2INT;DECLAREscorecursorCURSORFORSELECTsno,sname,enterscoreFROMstudent;DECLARECONTINUEHANDLERFORNOTFOUNDSETdone=1;SETn1=0,n2=0;OPENscorecursor;REPEATFETCHscorecursorINTOvno,vname,vscore;IFdone=0THENIFvscore>=680THENSETvaward="特等獎";SETn1=n1+1;SELECTvnoAS學(xué)號,vnameAS姓名,vawardAS獎勵等級;ELSEIFvscore>=660THENSETvaward="優(yōu)秀獎";SETn2=n2+1;SELECTvnoAS學(xué)號,vnameAS姓名,vawardAS獎勵等級;ELSESETvaward=NULL;ENDIF;ENDIF;UNTILdone=1ENDREPEAT;CLOSEscorecursor;SELECTn1AS特等獎人數(shù),n2AS優(yōu)秀獎人數(shù);END$$DELIMITER;調(diào)用這個存儲過程。mysql>CALLp_award();+--------------+--------+----------+|學(xué)號|姓名|獎勵等級|+--------------+--------+----------+|120211010103|宋洪博|特等獎|+--------------+--------+----------+1rowinset(0.00sec)+--------------+------+----------+|學(xué)號|姓名|獎勵等級|+--------------+------+----------+|120211050101|張函|優(yōu)秀獎|+--------------+------+----------+1rowinset(0.01sec)+--------------+------+----------+|學(xué)號|姓名|獎勵等級|+--------------+------+----------+|120211060104|王剛|優(yōu)秀獎|+--------------+------+----------+1rowinset(0.01sec)+------------+------------+|特等獎人數(shù)|優(yōu)秀獎人數(shù)|+------------+------------+|1|2|+------------+------------+【例8-19】創(chuàng)建一個包含游標(biāo)的存儲過程p_avgage,計算學(xué)生表student中學(xué)生的平均年齡。

分析:學(xué)生表student中只有出生日期birthdate字段,可以用游標(biāo)取得包含全部學(xué)生的出生日期birthdate字段結(jié)果集,然后逐一從結(jié)果集中取出記錄,分別用日期函數(shù)計算出每個學(xué)生的年齡進(jìn)行累加、并統(tǒng)計學(xué)生人數(shù),結(jié)果集中的記錄全部取出后,用年齡的累加和除以學(xué)生人數(shù)即可得到平均年齡。DELIMITER$$CREATEPROCEDUREp_avgage()BEGINDECLAREdoneINTdefault0;DECLAREVAGEdate;DECLAREvavgageFLOATDEFAULT0;DECLAREnINTDEFAULT0;DECLAREagecursorCURSORFORSELECTbirthdateFROMstudent;DECLARECONTINUEHANDLERFORNOTFOUNDSETdone=1;OPENagecursor;REPEATFETCHagecursorINTOvage;IFdone=0THENSETvavgage=vavgage+Year(NOW())-Year(vage);SETn=n+1;ENDIF;UNTILdone=1ENDREPEAT;SETvavgage=vavgage/n;SELECTvavgageAS學(xué)生平均年齡;CLOSEagecursor;END$$DELIMITER;調(diào)用這個存儲過程。mysql>CALLp_avgage();+--------------+|學(xué)生平均年齡|+--------------+|19.3333|+--------------+8.3存儲函數(shù)MySQL的存儲函數(shù)與存儲過程的作用和格式有許多類似之處,都是由聲明式SQL語句和過程式SQL語句組成的主要區(qū)別:(1)存儲函數(shù)有返回值,所以沒有輸出參數(shù)。(2)存儲函數(shù)不能使用CALL語句來調(diào)用,它的調(diào)用類似于系統(tǒng)的內(nèi)置函數(shù),放在表達(dá)式、賦值語句中實(shí)現(xiàn)調(diào)用。(3)存儲函數(shù)必須包含一條RETURN語句。8.3.1創(chuàng)建存儲函數(shù)使用CREATEFUNCTION語句可以創(chuàng)建存儲函數(shù)語法格式:CREATEFUNCTION存儲函數(shù)名([參數(shù)1[,參數(shù)2

]])RETURNS類型DETERMINISTIC存儲函數(shù)體

說明

(1)存儲函數(shù)名:用戶自定義的存儲函數(shù)名稱。(2)參數(shù):用于指定存儲函數(shù)的參數(shù),參數(shù)只有參數(shù)名和參數(shù)類型。不能為參數(shù)指定IN、OUT或INOUT的形式。(3)RETURNS子句:用于聲明存儲函數(shù)返回值的數(shù)據(jù)類型。(4)DETERMINISTIC:表示存儲函數(shù)的結(jié)果是確定的,不同用戶輸入相同的數(shù)據(jù)會返回相同的結(jié)果。(5)存儲過程體:存儲函數(shù)體中必須包含一條RETURNvalue語句,value用于指定存儲函數(shù)的返回值;在存儲過程中使用的SQL語句在存儲函數(shù)中也適用,包括流程控制語句、游標(biāo)等,多條語句需要存放在以BEGIN開始,END為結(jié)束的結(jié)構(gòu)中。8.3.2調(diào)用存儲函數(shù)存儲函數(shù)的調(diào)用類似于系統(tǒng)函數(shù)的調(diào)用,可以使用SELECT關(guān)鍵字。語法格式:SELECT存儲函數(shù)名([參數(shù)1[,參數(shù)2

]]);【例8-20】創(chuàng)建無參數(shù)的存儲函數(shù)f_count,實(shí)現(xiàn)統(tǒng)計學(xué)生表student中的學(xué)生人數(shù)。創(chuàng)建存儲函數(shù),RETURN語句將返回學(xué)生人數(shù)。DELIMITER$$CREATEFUNCTIONf_count()RETURNSINTDETERMINISTICBEGINRETURN(SELECTCOUNT(sno)FROMstudent);END$$DELIMITER;調(diào)用存儲函數(shù)f_count,雖然該存儲函數(shù)沒有參數(shù),但是調(diào)用時必須包含括號()。mysql>SELECTf_count();+-----------+|f_count()|+-----------+|15|+-----------+【例8-21】創(chuàng)建帶參數(shù)的存儲函數(shù)f_deptname,實(shí)現(xiàn)輸入學(xué)生姓名sname,返回該學(xué)生所在院系名稱deptname。創(chuàng)建存儲函數(shù),RETURN語句將返回院系名稱deptname。DELIMITER$$CREATEFUNCTIONf_deptname(vsnameCHAR(50))RETURNSCHAR(50)DETERMINISTICBEGINRETURN(SELECTdeptnameFROMdepartmentJOINstudentONdepartment.deptno=student.deptnoWHEREsname=vsname);END$$DELIMITER;使用姓名為“李華”作為參數(shù),調(diào)用存儲函數(shù)f_deptname。mysql>SELECTf_deptname("李華");運(yùn)行結(jié)果如下。+--------------------+|f_deptname("李華")|+--------------------+|電氣與電子工程學(xué)院|+--------------------+再次使用姓名為“劉向志”作為參數(shù),調(diào)用存儲函數(shù)f_deptname。mysql>SELECTf_deptname("劉向志");運(yùn)行結(jié)果如下。+----------------------+|f_deptname("劉向志")|+----------------------+|外國語學(xué)院|+----------------------+8.3.3刪除存儲函數(shù)當(dāng)存儲函數(shù)不再需要時,可以使用DROPFUNCTION語句刪除語法格式DROPFUNCTION[IFEXISTS]存儲函數(shù)名;說明:(1)存儲函數(shù)名:需要刪除的存儲函數(shù)名稱。(2)IFEXISTS:可選項(xiàng),檢測指定的存儲函數(shù)名是否存在,存在時才執(zhí)行刪除??梢员苊庥捎诖鎯瘮?shù)不存在而引起的錯誤。【例8-22】刪除存儲函數(shù)f_count。mysql>DROPFUNCTIONIFEXISTSf_count;8.4觸發(fā)器觸發(fā)器是一種特殊的存儲過程,用于保護(hù)表中數(shù)據(jù)來實(shí)現(xiàn)數(shù)據(jù)庫的數(shù)據(jù)完整性。它不需要使用CALL語句調(diào)用,也不需要直接寫出觸發(fā)器名來調(diào)用。當(dāng)有操作會影響到觸發(fā)器保護(hù)的數(shù)據(jù)時,觸發(fā)器會自動激活執(zhí)行,保證了數(shù)據(jù)庫的數(shù)據(jù)完整性。例如,當(dāng)要修改學(xué)生表student中某個學(xué)生的學(xué)號sno字段時,為了保持?jǐn)?shù)據(jù)的一致性,該學(xué)生在選修成績表score中的所有學(xué)號sno字段也要同時更新;在學(xué)生表student中刪除一個學(xué)生的記錄時,該學(xué)生在選修成績表score中的所有記錄也要同時刪除,否則將會出現(xiàn)成績沒有隸屬學(xué)生的數(shù)據(jù)不一致的情況。8.4.1創(chuàng)建觸發(fā)器使用CREATETRIGGER語句可以創(chuàng)建觸發(fā)器語法格式:CREATETRIGGER觸發(fā)器名觸發(fā)時間觸發(fā)事件ON表名FOREACHROW觸發(fā)器動作;

說明

(1)觸發(fā)器名:用戶自定義的觸發(fā)器名稱。(2)觸發(fā)時間:觸發(fā)器觸發(fā)的時刻,有AFTER和BEFORE兩個選項(xiàng),分別表示觸發(fā)動作是在觸發(fā)事件之前執(zhí)行,還是在觸發(fā)事件之后執(zhí)行。如果想在觸發(fā)事件之后執(zhí)行更多的改變操作,通常使用AFTER;如果想在觸發(fā)事件之前驗(yàn)證新數(shù)據(jù)是否滿足使用的限制,則使用BEFORE。(3)觸發(fā)事件:激活觸發(fā)器程序的語句包括INSERT、UPDATE和DELETE,即當(dāng)在表中插入、修改或刪除記錄時都會激活觸發(fā)器。(4)表名:與觸發(fā)器相關(guān)的表名,在該表上發(fā)生觸發(fā)事件才會激活觸發(fā)器。(5)FOREACHROW:用于指定每一行都可以激活觸發(fā)器。(6)觸發(fā)器動作:觸發(fā)器的主體,包含觸發(fā)器激活時將要執(zhí)行的語句。如果要執(zhí)行多條語句,則需要放置在以BEGIN開始,END為結(jié)束的結(jié)構(gòu)中。【例8-23】在課程表course中創(chuàng)建一個觸發(fā)器t_courseadd,每當(dāng)插入一條記錄后,給用戶變量@str賦值為“添加一門課程”。①

創(chuàng)建觸發(fā)器t_courseadd。mysql>CREATETRIGGERt_courseaddAFTERINSERT->ONcourseFOREACHROW->SET@str="添加一門課程";②

在課程表course中插入一條新記錄。mysql>INSERTINTOcourseVALUES("12345678","操作系統(tǒng)",64);③

查詢用戶變量@str,驗(yàn)證觸發(fā)器的執(zhí)行結(jié)果。mysql>SELECT@str;用戶變量@str的顯示結(jié)果如下。+--------------+|@str|+--------------+|添加一門課程|+--------------+8.4.2使用觸發(fā)器在觸發(fā)器的SQL語句中,可以使用表中的任何字段,為了避免引起系統(tǒng)混淆,不可以直接使用字段名稱,需要使用“OLD.字段名稱”或“NEW.字段名稱”來標(biāo)識?!癘LD.字段名稱”引用被修改或刪除前的值“NEW.字段名稱”引用新插入或修改的值。對于INSERT語句,只有NEW是合法的;對于DELETE語句,只有OLD是合法的;對于UPDATE語句,可以同時使用NEW和OLD。1.INSERT觸發(fā)器【例8-24】在學(xué)生表student中創(chuàng)建一個觸發(fā)器t_studentadd,每當(dāng)插入一條記錄后,顯示所插入記錄的學(xué)生的姓名。①

創(chuàng)建觸發(fā)器t_studentadd,將新插入記錄的sname值賦值給用戶變量@str。mysql>CREATETRIGGERt_studentaddAFTERINSERT->ONstudentFOREACHROW->SET@str=NEW.sname;②

在學(xué)生表student中插入一條新記錄。mysql>INSERTINTOstudentVALUES("120211010123","趙紅","女","2002-12-23",NULL,NULL,"101",670,NULL);③

查詢用戶變量@str,驗(yàn)證觸發(fā)器的執(zhí)行結(jié)果。mysql>SELECT@str;用戶變量@str的執(zhí)行結(jié)果如下。+------+|@str|+------+|趙紅|+------+2.UPDATE觸發(fā)器【例8-25】

在學(xué)生表student中創(chuàng)建一個觸發(fā)器t_sname,每當(dāng)修改一條學(xué)生記錄前,要保證外籍學(xué)生姓名sname字段一定是大寫。①

創(chuàng)建觸發(fā)器t_sname,修改學(xué)生表student的一條記錄前,將sname字段轉(zhuǎn)換為大寫。mysql>CREATETRIGGERt_snameBEFOREUPDATE->ONstudentFOREACHROW->SETNEW.sname=UPPER(NEW.sname);②

將學(xué)生表student中姓名sname為“趙紅”的記錄的姓名修改為“mary”。mysql>UPDATEstudentSETsname="mary"WHEREsname="趙紅";③

查詢學(xué)生表student中該記錄的修改情況,以驗(yàn)證觸發(fā)器。mysql>SELECTsno,sname,sexFROMstudent;+--------------+--------+------+|sno|sname|sex|+--------------+--------+------+|120211010103|宋洪博|男||120211010105|劉向志|男||120211010123|MARY|女||120211010230|李媛媛|女||120211030110|王琦|男||120211030409|張虎|男||120211040101|王曉紅|女||120211040108|李明|男||120211041102|李華|女||120211041129|侯明斌|男||120211050101|張函|女||120211050102|唐明卿|女||120211060104|王剛|男||120211060206|趙壯|男||120211070101|李淑子|女||120211070106|劉麗|女|+--------------+--------+------+3.DELETE觸發(fā)器【例8-26】在學(xué)生表student中創(chuàng)建一個觸發(fā)器t_studentdel,在刪除一條學(xué)生記錄前,將所刪除的記錄保存到student_archive表中。student_archive表結(jié)構(gòu)與student基本相同,但增加了具有自增屬性的字段id,且該字段是主鍵。①

創(chuàng)建student_archive表。mysql>CREATETABLEstudent_archive->(->idINTPRIMARYKEYAUTO_INCREMENT,->snoCHAR(12),->snameVARCHAR(50),->sexCHAR(1),->birthdateDATE,->partyVARCHAR(50),->classnoVARCHAR(20),->deptnoCHAR(3),->enterscoreINT,->awardsTEXT->);②

創(chuàng)建觸發(fā)器t_studentdel,在刪除一條學(xué)生記錄前,將該記錄插入到student_archive表中。mysql>CREATETRIGGERt_studentdelBEFOREDELETE->ONstudentFOREACHROW->INSERTINTOstudent_archive(sno,sname,sex,birthdate,party,classno,deptno,enterscore,awards)->VALUES(OLD.sno,OLD.sname,OLD.sex,OLD.birthdate,OLD.party,OLD.classno,OLD.deptno,OLD.enterscore,OLD.awards);③

刪除student表中學(xué)號sno為“120211010123”的學(xué)生。mysql>DELETEFROMstudentWHEREsno="120211010123";④

查詢student_archive表的記錄,以驗(yàn)證觸發(fā)器。mysql>SELECT*FROMstudent_archive;查詢結(jié)果如下。+---+------------+-------+-----+-----------+-----+--------+------+-----------+-------+|id|sno|sname|sex|birthdate|party|classno|deptno|enterscore|awards|+---+------------+-------+-----+-----------+-----+--------+------+-----------+-------+|1|120211010123|MARY|女|2002-12-23|NULL|NULL|101|670|NULL|+---+------------+-------+-----+-----------+-----+--------+------+-----------+-------+8.4.3查看觸發(fā)器(1)使用SHOWTRIGGER語句查看觸發(fā)器SHOWTRIGGER語句可以查看當(dāng)前數(shù)據(jù)庫中的所有觸發(fā)器,其語法格式如下。SHOWTRIGGERS;(2)在TRIGGERS表中查看觸發(fā)器在MySQL中,所有觸發(fā)器的定義都保存在information_schema數(shù)據(jù)庫的triggers表中,可以使用SELECT語句查看觸發(fā)器的詳細(xì)信息。查看所有觸發(fā)器的詳細(xì)信息。SELECT*FROMinformation_schema.triggers;也可以查看指定觸發(fā)器的詳細(xì)信息。8.4.4刪除觸發(fā)器可以使用DROP語句刪除觸發(fā)器語法格式DROPTRIGGER[IFEXISTS][數(shù)據(jù)庫名.]觸發(fā)器名;如果沒有指定數(shù)據(jù)庫的名稱,則默認(rèn)為當(dāng)前數(shù)據(jù)庫。當(dāng)刪除一個表時,該表中的觸發(fā)器被同時自動刪除。【例8-27】刪除觸發(fā)器t_studentdel。mysql>DROPTRIGGERt_studentdel;8.5事件事件(event)是在指定時刻才被執(zhí)行的過程式數(shù)據(jù)庫對象。一個事件可以在事件調(diào)度器的管理下周期性的啟動。事件和觸發(fā)器類似,都是在某些事情發(fā)生時啟動的,所以事件也被稱為臨時性觸發(fā)器。它們的區(qū)別在于觸發(fā)器是基于每張表所產(chǎn)生的某個操作(插入、修改、刪除等)來觸發(fā)的,而事件是基于特定的時間周期來觸發(fā)的。事件調(diào)度器必須是開啟狀態(tài)才可以使用。創(chuàng)建事件前可以用“SELECT@@EVENT_SCHEDULER;”命令查看事件調(diào)度器的狀態(tài),ON表示開啟;OFF表示關(guān)閉。如果事件調(diào)度器處于關(guān)閉狀態(tài),可以使用“SETGLOBALEVENT_SCHEDULER=1;”命令進(jìn)行開啟。8.5.1創(chuàng)建事件使用CREATEEVENT語句可以創(chuàng)建事件語法格式:CREATEEVENT事件名ONSCHEDULE時間調(diào)度DO觸發(fā)事件;

說明

(1)事件名:用戶自定義的事件名稱。(2)時間調(diào)度:指定事件何時發(fā)生或每隔多久發(fā)生一次,可以有以下2個取值。①AT時間點(diǎn)[+INTERVAL時間間隔]:表示在指定的時間點(diǎn)事件發(fā)生,如果有時間間隔,則表示在這個時間間隔后事件發(fā)生。②EVERY時間間隔[STARTS時間點(diǎn)[+INTERVAL時間間隔]][END時間點(diǎn)[+INTERVAL時間間隔]]:表示事件在指定的時間區(qū)間內(nèi),每間隔多長時間發(fā)生一次。其中,STARTS指定開始時間,END指定結(jié)束時間。(3)觸發(fā)事件:包含事件激活時將要執(zhí)行的語句。可以是一條SQL語句,也可以是BEGIN

END語句塊或者是一個存儲過程?!纠?-28】創(chuàng)建立即執(zhí)行的事件e_createtb,完成創(chuàng)建一張表timetb。mysql>CREATEEVENTe_createtb->ONSCHEDULEATNOW()->DO->CREATETABLEtimetb->(->noINTPRIMARYKEYAUTO_INCREMENT,->timefdTIME->);mysql>SELECT*FROMtimetb;Emptyset(0.02sec)【例8-29】創(chuàng)建事件e_instb,每10秒向表timetb中插入一條記錄。mysql>CREATEEVENTe_instb->ONSCHEDULEEVERY10SECOND->DO->INSERTINTOtimetb(tim

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論