@[toc]
視圖是什么
視圖在數(shù)據(jù)庫(kù)中的作用類似于窗戶,用戶可以通過這個(gè)窗口看到只對(duì)自己有用的數(shù)據(jù)宴卖。既保障了數(shù)據(jù)的安全性滋将,又大大提高了查詢效率。
MySQL 視圖(View)是一種虛擬存在的表症昏,同真實(shí)表一樣随闽,視圖也由列和行構(gòu)成,但視圖并不實(shí)際存在于數(shù)據(jù)庫(kù)中肝谭。行和列的數(shù)據(jù)來自于定義視圖的查詢中所使用的表掘宪,并且還是在使用視圖時(shí)動(dòng)態(tài)生成的。
數(shù)據(jù)庫(kù)中只存放了視圖的定義分苇,并沒有存放視圖中的數(shù)據(jù)添诉,這些數(shù)據(jù)都存放在定義視圖查詢所引用的真實(shí)表中。使用視圖查詢數(shù)據(jù)時(shí)医寿,數(shù)據(jù)庫(kù)會(huì)從真實(shí)表中取出對(duì)應(yīng)的數(shù)據(jù)栏赴。因此,視圖中的數(shù)據(jù)是依賴于真實(shí)表中的數(shù)據(jù)的靖秩。一旦真實(shí)表中的數(shù)據(jù)發(fā)生改變须眷,顯示在視圖中的數(shù)據(jù)也會(huì)發(fā)生改變。
視圖可以從原有的表上選取對(duì)用戶有用的信息沟突,那些對(duì)用戶沒用花颗,或者用戶沒有權(quán)限了解的信息,都可以直接屏蔽掉惠拭,作用類似于篩選扩劝。這樣做既使應(yīng)用簡(jiǎn)單化庸论,也保證了系統(tǒng)的安全。
例如棒呛,下面的數(shù)據(jù)庫(kù)中有一張公司部門表 department聂示。表中包括部門號(hào)(d_id)、部門名稱(d_name)簇秒、功能(function)和辦公地址(address)鱼喉。department 表的結(jié)構(gòu)如下:
mysql> DESC department;
+----------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+----------+-------------+------+-----+---------+-------+
| d_id | int(4) | NO | PRI | NULL | |
| d_name | varchar(20) | NO | UNI | NULL | |
| function | varchar(50) | YES | | NULL | |
| address | varchar(50) | YES | | NULL | |
+----------+-------------+------+-----+---------+-------+
4 rows in set (0.02 sec)
還有一張員工表 worker。表中包含了員工的工作號(hào)(num)趋观、部門號(hào)(d_id)扛禽、姓名(name)、性別(sex)皱坛、出生日期(birthday)和家庭住址(homeaddress)编曼。worker 表的結(jié)構(gòu)如下:
mysql> DESC worker;
+-------------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------------+-------------+------+-----+---------+-------+
| num | int(10) | NO | PRI | NULL | |
| d_id | int(4) | YES |MUL | NULL | |
| name | varchar(20) | NO | | NULL | |
| sex | varchar(4) | NO | | NULL | |
| birthday | datetime | YES | | NULL | |
| homeaddress | varchar(50) | YES | | NULL | |
+-------------+-------------+------+-----+---------+-------+
6 rows in set (0.01 sec)
由于各部門領(lǐng)導(dǎo)的權(quán)力范圍不同,因此麸恍,各部門的領(lǐng)導(dǎo)只能看到該部門的員工信息灵巧;而且,領(lǐng)導(dǎo)可能不關(guān)心員工的生日和家庭住址抹沪。為了達(dá)到這個(gè)目的刻肄,可以為各部門的領(lǐng)導(dǎo)建立一個(gè)視圖,通過該視圖融欧,領(lǐng)導(dǎo)只能看到本部門員工的指定信息敏弃。
- 例如,為生產(chǎn)部門建立一個(gè)名為 product view 的視圖噪馏。通過視圖 product view麦到,生產(chǎn)部門的領(lǐng)導(dǎo)只能看到生產(chǎn)部門員工的工作號(hào)、姓名和性別等信息欠肾。這些 department 表的信息和 worker 表的信息依然存在于各自的表中瓶颠,而視圖 product_view 中不保存任何數(shù)據(jù)信息。當(dāng) department 表和 worker 表的信息發(fā)生改變時(shí)刺桃,視圖 product_view 顯示的信息也會(huì)發(fā)生相應(yīng)的變化粹淋。
技巧:如果經(jīng)常需要從多個(gè)表查詢指定字段的數(shù)據(jù),可以在這些表上建立一個(gè)視圖瑟慈,通過這個(gè)視圖顯示這些字段的數(shù)據(jù)桃移。
MySQL 的視圖不支持輸入?yún)?shù)的功能,因此交互性上還有欠缺葛碧。但對(duì)于變化不是很大的操作借杰,使用視圖可以很大程度上簡(jiǎn)化用戶的操作。
視圖并不同于數(shù)據(jù)表进泼,它們的區(qū)別在于以下幾點(diǎn):
- 視圖不是數(shù)據(jù)庫(kù)中真實(shí)的表蔗衡,而是一張?zhí)摂M表纤虽,其結(jié)構(gòu)和數(shù)據(jù)是建立在對(duì)數(shù)據(jù)中真實(shí)表的查詢基礎(chǔ)上的。
- 存儲(chǔ)在數(shù)據(jù)庫(kù)中的查詢操作 SQL 語(yǔ)句定義了視圖的內(nèi)容粘都,列數(shù)據(jù)和行數(shù)據(jù)來自于視圖查詢所引用的實(shí)際表廓推,引用視圖時(shí)動(dòng)態(tài)生成這些數(shù)據(jù)刷袍。
- 視圖沒有實(shí)際的物理記錄翩隧,不是以數(shù)據(jù)集的形式存儲(chǔ)在數(shù)據(jù)庫(kù)中的,它所對(duì)應(yīng)的數(shù)據(jù)實(shí)際上是存儲(chǔ)在視圖所引用的真實(shí)表中的呻纹。
- 視圖是數(shù)據(jù)的窗口堆生,而表是內(nèi)容。表是實(shí)際數(shù)據(jù)的存放單位雷酪,而視圖只是以不同的顯示方式展示數(shù)據(jù)淑仆,其數(shù)據(jù)來源還是實(shí)際表。
- 視圖是查看數(shù)據(jù)表的一種方法哥力,可以查詢數(shù)據(jù)表中某些字段構(gòu)成的數(shù)據(jù)蔗怠,只是一些 SQL 語(yǔ)句的集合。從安全的角度來看吩跋,視圖的數(shù)據(jù)安全性更高寞射,使用視圖的用戶不接觸數(shù)據(jù)表,不知道表結(jié)構(gòu)见坑。
- 視圖的建立和刪除只影響視圖本身旷档,不影響對(duì)應(yīng)的基本表聘芜。
視圖的優(yōu)點(diǎn)
視圖與表在本質(zhì)上雖然不相同,但視圖經(jīng)過定義以后侵浸,結(jié)構(gòu)形式和表一樣,可以進(jìn)行查詢氛谜、修改掏觉、更新和刪除等操作。同時(shí)值漫,視圖具有如下優(yōu)點(diǎn):
1) 定制用戶數(shù)據(jù)澳腹,聚焦特定的數(shù)據(jù)
在實(shí)際的應(yīng)用過程中,不同的用戶可能對(duì)不同的數(shù)據(jù)有不同的要求惭嚣。
例如遵湖,當(dāng)數(shù)據(jù)庫(kù)同時(shí)存在時(shí),如學(xué)生基本信息表晚吞、課程表和教師信息表等多種表同時(shí)存在時(shí)延旧,可以根據(jù)需求讓不同的用戶使用各自的數(shù)據(jù)。學(xué)生查看修改自己基本信息的視圖槽地,安排課程人員查看修改課程表和教師信息的視圖迁沫,教師查看學(xué)生信息和課程信息表的視圖芦瘾。
2) 簡(jiǎn)化數(shù)據(jù)操作
在使用查詢時(shí),很多時(shí)候要使用聚合函數(shù)集畅,同時(shí)還要顯示其他字段的信息近弟,可能還需要關(guān)聯(lián)到其他表,語(yǔ)句可能會(huì)很長(zhǎng)挺智,如果這個(gè)動(dòng)作頻繁發(fā)生的話祷愉,可以創(chuàng)建視圖來簡(jiǎn)化操作。
3) 提高數(shù)據(jù)的安全性
視圖是虛擬的赦颇,物理上是不存在的二鳄。可以只授予用戶視圖的權(quán)限媒怯,而不具體指定使用表的權(quán)限订讼,來保護(hù)基礎(chǔ)數(shù)據(jù)的安全。
4) 共享所需數(shù)據(jù)
通過使用視圖扇苞,每個(gè)用戶不必都定義和存儲(chǔ)自己所需的數(shù)據(jù)欺殿,可以共享數(shù)據(jù)庫(kù)中的數(shù)據(jù),同樣的數(shù)據(jù)只需要存儲(chǔ)一次鳖敷。
5) 更改數(shù)據(jù)格式
通過使用視圖脖苏,可以重新格式化檢索出的數(shù)據(jù),并組織輸出到其他應(yīng)用程序中哄陶。
6) 重用 SQL 語(yǔ)句
視圖提供的是對(duì)查詢操作的封裝帆阳,本身不包含數(shù)據(jù),所呈現(xiàn)的數(shù)據(jù)是根據(jù)視圖定義從基礎(chǔ)表中檢索出來的屋吨,如果基礎(chǔ)表的數(shù)據(jù)新增或刪除蜒谤,視圖呈現(xiàn)的也是更新后的數(shù)據(jù)。視圖定義后至扰,編寫完所需的查詢鳍徽,可以方便地重用該視圖。
要注意區(qū)別視圖和數(shù)據(jù)表的本質(zhì)敢课,即視圖是基于真實(shí)表的一張?zhí)摂M的表阶祭,其數(shù)據(jù)來源均建立在真實(shí)表的基礎(chǔ)上。
使用視圖的時(shí)候直秆,還應(yīng)該注意以下幾點(diǎn):
- 創(chuàng)建視圖需要足夠的訪問權(quán)限濒募。
- 創(chuàng)建視圖的數(shù)目沒有限制。
- 視圖可以嵌套圾结,即從其他視圖中檢索數(shù)據(jù)的查詢來創(chuàng)建視圖瑰剃。
- 視圖不能索引,也不能有關(guān)聯(lián)的觸發(fā)器筝野、默認(rèn)值或規(guī)則晌姚。
- 視圖可以和表一起使用粤剧。
- 視圖不包含數(shù)據(jù),所以每次使用視圖時(shí)挥唠,都必須執(zhí)行查詢中所需的任何一個(gè)檢索操作抵恋。如果用多個(gè)連接和過濾條件創(chuàng)建了復(fù)雜的視圖或嵌套了視圖,可能會(huì)發(fā)現(xiàn)系統(tǒng)運(yùn)行性能下降得十分嚴(yán)重宝磨。因此弧关,在部署大量視圖應(yīng)用時(shí),應(yīng)該進(jìn)行系統(tǒng)測(cè)試懊烤。
提示:ORDER BY 子句可以用在視圖中梯醒,但若該視圖檢索數(shù)據(jù)的 SELECT 語(yǔ)句中也含有 ORDER BY 子句,則該視圖中的 ORDER BY 子句將被覆蓋腌紧。
MySQL創(chuàng)建視圖
創(chuàng)建視圖是指在已經(jīng)存在的 MySQL 數(shù)據(jù)庫(kù)表上建立視圖。視圖可以建立在一張表中畜隶,也可以建立在多張表中壁肋。
基本語(yǔ)法
可以使用 CREATE VIEW 語(yǔ)句來創(chuàng)建視圖。
語(yǔ)法格式如下:
CREATE VIEW <視圖名> AS <SELECT語(yǔ)句>
語(yǔ)法說明如下籽慢。
-
<視圖名>
:指定視圖的名稱浸遗。該名稱在數(shù)據(jù)庫(kù)中必須是唯一的,不能與其他表或視圖同名箱亿。 -
<SELECT語(yǔ)句>
:指定創(chuàng)建視圖的 SELECT 語(yǔ)句跛锌,可用于查詢多個(gè)基礎(chǔ)表或源視圖。
對(duì)于創(chuàng)建視圖中的 SELECT 語(yǔ)句的指定存在以下限制:
- 用戶除了擁有 CREATE VIEW 權(quán)限外届惋,還具有操作中涉及的基礎(chǔ)表和其他視圖的相關(guān)權(quán)限髓帽。
- SELECT 語(yǔ)句不能引用系統(tǒng)或用戶變量。
- SELECT 語(yǔ)句不能包含 FROM 子句中的子查詢脑豹。
- SELECT 語(yǔ)句不能引用預(yù)處理語(yǔ)句參數(shù)郑藏。
視圖定義中引用的表或視圖必須存在。但是瘩欺,創(chuàng)建完視圖后必盖,可以刪除定義引用的表或視圖【愣觯可使用 CHECK TABLE 語(yǔ)句檢查視圖定義是否存在這類問題歌粥。
視圖定義中允許使用 ORDER BY 語(yǔ)句,但是若從特定視圖進(jìn)行選擇拍埠,而該視圖使用了自己的 ORDER BY 語(yǔ)句失驶,則視圖定義中的 ORDER BY 將被忽略。
視圖定義中不能引用 TEMPORARY 表(臨時(shí)表)械拍,不能創(chuàng)建 TEMPORARY 視圖突勇。
WITH CHECK OPTION 的意思是装盯,修改視圖時(shí),檢查插入的數(shù)據(jù)是否符合 WHERE 設(shè)置的條件甲馋。
查詢視圖
視圖一經(jīng)定義之后埂奈,就可以如同查詢數(shù)據(jù)表一樣,使用 SELECT 語(yǔ)句查詢視圖中的數(shù)據(jù)定躏,語(yǔ)法和查詢基礎(chǔ)表的數(shù)據(jù)一樣账磺。
視圖用于查詢主要應(yīng)用在以下幾個(gè)方面:
- 使用視圖重新格式化檢索出的數(shù)據(jù)。
- 使用視圖簡(jiǎn)化復(fù)雜的表連接痊远。
- 使用視圖過濾數(shù)據(jù)垮抗。
DESCRIBE 可以用來查看視圖,語(yǔ)法如下:
DESCRIBE 視圖名碧聪;
注意:DESCRIBE 一般情況下可以簡(jiǎn)寫成 DESC冒版,輸入這個(gè)命令的執(zhí)行結(jié)果和輸入 DESCRIBE 是一樣的。
MySQL查看視圖
創(chuàng)建好視圖后逞姿,可以通過查看視圖的語(yǔ)句來查看視圖的字段信息以及詳細(xì)信息辞嗡。
查看視圖的字段信息
查看視圖的字段信息與查看數(shù)據(jù)表的字段信息一樣,都是使用 DESCRIBE 關(guān)鍵字來查看的滞造。具體語(yǔ)法如下:
DESCRIBE 視圖名;
或簡(jiǎn)寫成:
DESC 視圖名;
查看視圖的字段內(nèi)容與查看表的字段內(nèi)容顯示的格式是相同的续室。因此,更能說明視圖實(shí)際上也是一張數(shù)據(jù)表了谒养,不同的是挺狰,視圖中的數(shù)據(jù)都來自于數(shù)據(jù)庫(kù)中已經(jīng)存在的表。
查看視圖的詳細(xì)信息
在 MySQL 中买窟,SHOW CREATE VIEW 語(yǔ)句可以查看視圖的詳細(xì)定義丰泊。其語(yǔ)法如下所示:
SHOW CREATE VIEW 視圖名;
所有視圖的定義都是存儲(chǔ)在 information_schema 數(shù)據(jù)庫(kù)下的 views 表中,也可以在這個(gè)表中查看所有視圖的詳細(xì)信息蔑祟,SQL 語(yǔ)句如下:
SELECT * FROM information_schema.views;
不過趁耗,通常情況下都是使用 SHOW CREATE VIEW 語(yǔ)句。
MySQL修改視圖
修改視圖是指修改 MySQL 數(shù)據(jù)庫(kù)中存在的視圖疆虚,當(dāng)基本表的某些字段發(fā)生變化時(shí)苛败,可以通過修改視圖來保持與基本表的一致性。
基本語(yǔ)法
可以使用 ALTER VIEW 語(yǔ)句來對(duì)已有的視圖進(jìn)行修改径簿。
語(yǔ)法格式如下:
ALTER VIEW <視圖名> AS <SELECT語(yǔ)句>
語(yǔ)法說明如下:
-
<視圖名>
:指定視圖的名稱罢屈。該名稱在數(shù)據(jù)庫(kù)中必須是唯一的,不能與其他表或視圖同名篇亭。 -
<SELECT 語(yǔ)句>
:指定創(chuàng)建視圖的 SELECT 語(yǔ)句缠捌,可用于查詢多個(gè)基礎(chǔ)表或源視圖。
需要注意的是,對(duì)于 ALTER VIEW 語(yǔ)句的使用曼月,需要用戶具有針對(duì)視圖的 CREATE VIEW 和 DROP 權(quán)限谊却,以及由 SELECT 語(yǔ)句選擇的每一列上的某些權(quán)限。
修改視圖的定義哑芹,除了可以通過 ALTER VIEW 外炎辨,也可以使用 DROP VIEW 語(yǔ)句先刪除視圖,再使用 CREATE VIEW 語(yǔ)句來實(shí)現(xiàn)聪姿。
修改視圖內(nèi)容
視圖是一個(gè)虛擬表碴萧,實(shí)際的數(shù)據(jù)來自于基本表,所以通過插入末购、修改和刪除操作更新視圖中的數(shù)據(jù)破喻,實(shí)質(zhì)上是在更新視圖所引用的基本表的數(shù)據(jù)。
注意:對(duì)視圖的修改就是對(duì)基本表的修改盟榴,因此在修改時(shí)曹质,要滿足基本表的數(shù)據(jù)定義。
某些視圖是可更新的曹货。也就是說咆繁,可以使用 UPDATE、DELETE 或 INSERT 等語(yǔ)句更新基本表的內(nèi)容顶籽。對(duì)于可更新的視圖,視圖中的行和基本表的行之間必須具有一對(duì)一的關(guān)系银觅。
還有一些特定的其他結(jié)構(gòu)礼饱,這些結(jié)構(gòu)會(huì)使得視圖不可更新。更具體地講究驴,如果視圖包含以下結(jié)構(gòu)中的任何一種镊绪,它就是不可更新的:
- 聚合函數(shù) SUM()、MIN()洒忧、MAX()蝴韭、COUNT() 等。
- DISTINCT 關(guān)鍵字熙侍。
- GROUP BY 子句榄鉴。
- HAVING 子句。
- UNION 或 UNION ALL 運(yùn)算符蛉抓。
- 位于選擇列表中的子查詢庆尘。
- FROM 子句中的不可更新視圖或包含多個(gè)表。
- WHERE 子句中的子查詢巷送,引用 FROM 子句中的表驶忌。
- ALGORITHM 選項(xiàng)為 TEMPTABLE(使用臨時(shí)表總會(huì)使視圖成為不可更新的)的時(shí)候。
MySQL刪除視圖
刪除視圖是指刪除 MySQL 數(shù)據(jù)庫(kù)中已存在的視圖笑跛。刪除視圖時(shí)付魔,只能刪除視圖的定義聊品,不會(huì)刪除數(shù)據(jù)。
基本語(yǔ)法
可以使用 DROP VIEW 語(yǔ)句來刪除視圖几苍。
語(yǔ)法格式如下:
DROP VIEW <視圖名1> [ , <視圖名2> …]
其中:<視圖名>
指定要?jiǎng)h除的視圖名翻屈。DROP VIEW 語(yǔ)句可以一次刪除多個(gè)視圖,但是必須在每個(gè)視圖上擁有 DROP 權(quán)限擦剑。
索引是什么
索引是一種特殊的數(shù)據(jù)庫(kù)結(jié)構(gòu)妖胀,由數(shù)據(jù)表中的一列或多列組合而成,可以用來快速查詢數(shù)據(jù)表中有某一特定值的記錄惠勒。
通過索引赚抡,查詢數(shù)據(jù)時(shí)不用讀完記錄的所有信息,而只是查詢索引列纠屋。否則涂臣,數(shù)據(jù)庫(kù)系統(tǒng)將讀取每條記錄的所有信息進(jìn)行匹配。
可以把索引比作新華字典的音序表售担。例如赁遗,要查“庫(kù)”字,如果不使用音序族铆,就需要從字典的 400 頁(yè)中逐頁(yè)來找岩四。但是,如果提取拼音出來哥攘,構(gòu)成音序表剖煌,就只需要從 10 多頁(yè)的音序表中直接查找。這樣就可以大大節(jié)省時(shí)間逝淹。
因此耕姊,使用索引可以很大程度上提高數(shù)據(jù)庫(kù)的查詢速度,還有效的提高了數(shù)據(jù)庫(kù)系統(tǒng)的性能栅葡。
為什么要使用索引
索引就是根據(jù)表中的一列或若干列按照一定順序建立的列值與記錄行之間的對(duì)應(yīng)關(guān)系表茉兰,實(shí)質(zhì)上是一張描述索引列的列值與原表中記錄行之間一 一對(duì)應(yīng)關(guān)系的有序表。
索引是 MySQL 中十分重要的數(shù)據(jù)庫(kù)對(duì)象欣簇,是數(shù)據(jù)庫(kù)性能調(diào)優(yōu)技術(shù)的基礎(chǔ)规脸,常用于實(shí)現(xiàn)數(shù)據(jù)的快速檢索。
在 MySQL 中醉蚁,通常有以下兩種方式訪問數(shù)據(jù)庫(kù)表的行數(shù)據(jù):
順序訪問
順序訪問是在表中實(shí)行全表掃描燃辖,從頭到尾逐行遍歷,直到在無(wú)序的行數(shù)據(jù)中找到符合條件的目標(biāo)數(shù)據(jù)网棍。
順序訪問實(shí)現(xiàn)比較簡(jiǎn)單黔龟,但是當(dāng)表中有大量數(shù)據(jù)的時(shí)候,效率非常低下。例如氏身,在幾千萬(wàn)條數(shù)據(jù)中查找少量的數(shù)據(jù)時(shí)巍棱,使用順序訪問方式將會(huì)遍歷所有的數(shù)據(jù),花費(fèi)大量的時(shí)間蛋欣,顯然會(huì)影響數(shù)據(jù)庫(kù)的處理性能航徙。
索引訪問
索引訪問是通過遍歷索引來直接訪問表中記錄行的方式。
使用這種方式的前提是對(duì)表建立一個(gè)索引陷虎,在列上創(chuàng)建了索引之后到踏,查找數(shù)據(jù)時(shí)可以直接根據(jù)該列上的索引找到對(duì)應(yīng)記錄行的位置,從而快捷地查找到數(shù)據(jù)尚猿。索引存儲(chǔ)了指定列數(shù)據(jù)值的指針窝稿,根據(jù)指定的排序順序?qū)@些指針排序。
- 例如凿掂,在學(xué)生基本信息表 tb_students 中伴榔,如果基于 student_id 建立了索引,系統(tǒng)就建立了一張索引列到實(shí)際記錄的映射表庄萎。當(dāng)用戶需要查找 student_id 為 12022 的數(shù)據(jù)的時(shí)候踪少,系統(tǒng)先在 student_id 索引上找到該記錄,然后通過映射表直接找到數(shù)據(jù)行糠涛,并且返回該行數(shù)據(jù)援奢。因?yàn)閽呙杷饕乃俣纫话氵h(yuǎn)遠(yuǎn)大于掃描實(shí)際數(shù)據(jù)行的速度寒砖,所以采用索引的方式可以大大提高數(shù)據(jù)庫(kù)的工作效率自沧。
簡(jiǎn)而言之,不使用索引廊酣,MySQL 就必須從第一條記錄開始讀完整個(gè)表锉罐,直到找出相關(guān)的行。表越大绕娘,查詢數(shù)據(jù)所花費(fèi)的時(shí)間就越多脓规。如果表中查詢的列有一個(gè)索引,MySQL 就能快速到達(dá)一個(gè)位置去搜索數(shù)據(jù)文件险领,而不必查看所有數(shù)據(jù)侨舆,這樣將會(huì)節(jié)省很大一部分時(shí)間。
索引的優(yōu)缺點(diǎn)
索引有其明顯的優(yōu)勢(shì)绢陌,也有其不可避免的缺點(diǎn)挨下。
優(yōu)點(diǎn)
索引的優(yōu)點(diǎn)如下:
- 通過創(chuàng)建唯一索引可以保證數(shù)據(jù)庫(kù)表中每一行數(shù)據(jù)的唯一性。
- 可以給所有的 MySQL 列類型設(shè)置索引脐湾。
- 可以大大加快數(shù)據(jù)的查詢速度臭笆,這是使用索引最主要的原因。
- 在實(shí)現(xiàn)數(shù)據(jù)的參考完整性方面可以加速表與表之間的連接。
- 在使用分組和排序子句進(jìn)行數(shù)據(jù)查詢時(shí)也可以顯著減少查詢中分組和排序的時(shí)間
缺點(diǎn)
增加索引也有許多不利的方面愁铺,主要如下:
- 創(chuàng)建和維護(hù)索引組要耗費(fèi)時(shí)間鹰霍,并且隨著數(shù)據(jù)量的增加所耗費(fèi)的時(shí)間也會(huì)增加。
- 索引需要占磁盤空間茵乱,除了數(shù)據(jù)表占數(shù)據(jù)空間以外茂洒,每一個(gè)索引還要占一定的物理空間。如果有大量的索引瓶竭,索引文件可能比數(shù)據(jù)文件更快達(dá)到最大文件尺寸督勺。
- 當(dāng)對(duì)表中的數(shù)據(jù)進(jìn)行增加、刪除和修改的時(shí)候斤贰,索引也要?jiǎng)討B(tài)維護(hù)智哀,這樣就降低了數(shù)據(jù)的維護(hù)速度。
使用索引時(shí)腋舌,需要綜合考慮索引的優(yōu)點(diǎn)和缺點(diǎn)盏触。
索引可以提高查詢速度,但是會(huì)影響插入記錄的速度块饺。因?yàn)樵薇纾蛴兴饕谋碇胁迦胗涗洉r(shí),數(shù)據(jù)庫(kù)系統(tǒng)會(huì)按照索引進(jìn)行排序授艰,這樣就降低了插入記錄的速度辨嗽,插入大量記錄時(shí)的速度影響會(huì)更加明顯。
MySQL索引類型詳解
索引的類型和存儲(chǔ)引擎有關(guān)淮腾,每種存儲(chǔ)引擎所支持的索引類型不一定完全相同糟需。MySQL 索引可以從存儲(chǔ)方式、邏輯角度和實(shí)際使用的角度來進(jìn)行分類谷朝。
存儲(chǔ)方式區(qū)分
根據(jù)存儲(chǔ)方式的不同洲押,MySQL 中常用的索引在物理上分為 B-樹索引和 HASH 索引兩類,兩種不同類型的索引各有其不同的適用范圍圆凰。
B-樹索引
B-樹索引又稱為 BTREE 索引杈帐,目前大部分的索引都是采用 B-樹索引來存儲(chǔ)的。
B-樹索引是一個(gè)典型的數(shù)據(jù)結(jié)構(gòu)专钉,其包含的組件主要有以下幾個(gè):
- 葉子節(jié)點(diǎn):包含的條目直接指向表里的數(shù)據(jù)行挑童。葉子節(jié)點(diǎn)之間彼此相連,一個(gè)葉子節(jié)點(diǎn)有一個(gè)指向下一個(gè)葉子節(jié)點(diǎn)的指針跃须。
- 分支節(jié)點(diǎn):包含的條目指向索引里其他的分支節(jié)點(diǎn)或者葉子節(jié)點(diǎn)站叼。
- 根節(jié)點(diǎn):一個(gè) B-樹索引只有一個(gè)根節(jié)點(diǎn),實(shí)際上就是位于樹的最頂端的分支節(jié)點(diǎn)尽楔。
基于這種樹形數(shù)據(jù)結(jié)構(gòu)投储,表中的每一行都會(huì)在索引上有一個(gè)對(duì)應(yīng)值。因此翔试,在表中進(jìn)行數(shù)據(jù)查詢時(shí)轻要,可以根據(jù)索引值一步一步定位到數(shù)據(jù)所在的行。
B-樹索引可以進(jìn)行全鍵值垦缅、鍵值范圍和鍵值前綴查詢冲泥,也可以對(duì)查詢結(jié)果進(jìn)行 ORDER BY 排序。但 B-樹索引必須遵循左邊前綴原則壁涎,要考慮以下幾點(diǎn)約束:
- 查詢必須從索引的最左邊的列開始凡恍。
- 查詢不能跳過某一索引列,必須按照從左到右的順序進(jìn)行匹配怔球。
- 存儲(chǔ)引擎不能使用索引中范圍條件右邊的列嚼酝。
哈希索引
哈希(Hash)一般翻譯為“散列”,也有直接音譯成“哈暇固常”的闽巩,就是把任意長(zhǎng)度的輸入(又叫作預(yù)映射,pre-image)通過散列算法變換成固定長(zhǎng)度的輸出担汤,該輸出就是散列值涎跨。
哈希索引也稱為散列索引或 HASH 索引。MySQL 目前僅有 MEMORY 存儲(chǔ)引擎和 HEAP 存儲(chǔ)引擎支持這類索引崭歧。其中隅很,MEMORY 存儲(chǔ)引擎可以支持 B-樹索引和 HASH 索引,且將 HASH 當(dāng)成默認(rèn)索引率碾。
HASH 索引不是基于樹形的數(shù)據(jù)結(jié)構(gòu)查找數(shù)據(jù)叔营,而是根據(jù)索引列對(duì)應(yīng)的哈希值的方法獲取表的記錄行。哈希索引的最大特點(diǎn)是訪問速度快所宰,但也存在下面的一些缺點(diǎn):
- MySQL 需要讀取表中索引列的值來參與散列計(jì)算绒尊,散列計(jì)算是一個(gè)比較耗時(shí)的操作。也就是說仔粥,相對(duì)于 B-樹索引來說垒酬,建立哈希索引會(huì)耗費(fèi)更多的時(shí)間。
- 不能使用 HASH 索引排序件炉。
- HASH 索引只支持等值比較,如“=”“IN()”或“<=>”矮湘。
- HASH 索引不支持鍵的部分匹配斟冕,因?yàn)樵谟?jì)算 HASH 值的時(shí)候是通過整個(gè)索引值來計(jì)算的。
邏輯區(qū)分
根據(jù)索引的具體用途缅阳,MySQL 中的索引在邏輯上分為以下 5 類:
普通索引
普通索引是 MySQL 中最基本的索引類型磕蛇,它沒有任何限制景描,唯一任務(wù)就是加快系統(tǒng)對(duì)數(shù)據(jù)的訪問速度。
普通索引允許在定義索引的列中插入重復(fù)值和空值秀撇。
創(chuàng)建普通索引時(shí)超棺,通常使用的關(guān)鍵字是 INDEX 或 KEY。
唯一索引
唯一索引與普通索引類似呵燕,不同的是創(chuàng)建唯一性索引的目的不是為了提高訪問速度棠绘,而是為了避免數(shù)據(jù)出現(xiàn)重復(fù)。
唯一索引列的值必須唯一再扭,允許有空值氧苍。如果是組合索引,則列值的組合必須唯一泛范。
創(chuàng)建唯一索引通常使用 UNIQUE 關(guān)鍵字让虐。
主鍵索引
顧名思義,主鍵索引就是專門為主鍵字段創(chuàng)建的索引罢荡,也屬于索引的一種赡突。
主鍵索引是一種特殊的唯一索引,不允許值重復(fù)或者值為空区赵。
創(chuàng)建主鍵索引通常使用 PRIMARY KEY 關(guān)鍵字惭缰。不能使用 CREATE INDEX 語(yǔ)句創(chuàng)建主鍵索引。
空間索引
空間索引是對(duì)空間數(shù)據(jù)類型的字段建立的索引惧笛,使用 SPATIAL 關(guān)鍵字進(jìn)行擴(kuò)展从媚。
創(chuàng)建空間索引的列必須將其聲明為 NOT NULL,空間索引只能在存儲(chǔ)引擎為 MyISAM 的表中創(chuàng)建患整。
空間索引主要用于地理空間數(shù)據(jù)類型 GEOMETRY拜效。對(duì)于初學(xué)者來說,這類索引很少會(huì)用到各谚。
全文索引
全文索引主要用來查找文本中的關(guān)鍵字紧憾,只能在 CHAR、VARCHAR 或 TEXT 類型的列上創(chuàng)建昌渤。在 MySQL 中只有 MyISAM 存儲(chǔ)引擎支持全文索引赴穗。
全文索引允許在索引列中插入重復(fù)值和空值。
不過對(duì)于大容量的數(shù)據(jù)表膀息,生成全文索引非常消耗時(shí)間和硬盤空間般眉。
創(chuàng)建全文索引使用 FULLTEXT 關(guān)鍵字。
實(shí)際使用區(qū)分
索引在邏輯上分為以上 5 類潜支,但在實(shí)際使用中甸赃,索引通常被創(chuàng)建成單列索引和組合索引。
單列索引
單列索引就是索引只包含原表的一個(gè)列冗酿。在表中的單個(gè)字段上創(chuàng)建索引埠对,單列索引只根據(jù)該字段進(jìn)行索引络断。
單列索引可以是普通索引,也可以是唯一性索引项玛,還可以是全文索引貌笨。只要保證該索引只對(duì)應(yīng)一個(gè)字段即可。
多列索引
組合索引也稱為復(fù)合索引或多列索引襟沮。相對(duì)于單列索引來說锥惋,組合索引是將原表的多個(gè)列共同組成一個(gè)索引。多列索引是在表的多個(gè)字段上創(chuàng)建一個(gè)索引臣嚣。該索引指向創(chuàng)建時(shí)對(duì)應(yīng)的多個(gè)字段净刮,可以通過這幾個(gè)字段進(jìn)行查詢。但是硅则,只有查詢條件中使用了這些字段中第一個(gè)字段時(shí)淹父,索引才會(huì)被使用。
提示:一個(gè)表可以有多個(gè)單列索引怎虫,但這些索引不是組合索引暑认。一個(gè)組合索引實(shí)質(zhì)上為表的查詢提供了多個(gè)索引,以此來加快查詢速度大审。
- 比如蘸际,在一個(gè)表中創(chuàng)建了一個(gè)組合索引(c1,c2徒扶,c3)粮彤,在實(shí)際查詢中,系統(tǒng)用來實(shí)際加速的索引有三個(gè):?jiǎn)蝹€(gè)索引(c1)姜骡、雙列索引(c1导坟,c2)和多列索引(c1,c2圈澈,c3)惫周。
MySQL創(chuàng)建索引
創(chuàng)建索引是指在某個(gè)表的一列或多列上建立一個(gè)索引,可以提高對(duì)表的訪問速度康栈。創(chuàng)建索引對(duì) MySQL數(shù)據(jù)庫(kù)的高效運(yùn)行來說是很重要的递递。
基本語(yǔ)法
MySQL 提供了三種創(chuàng)建索引的方法:
使用 CREATE INDEX 語(yǔ)句
可以使用專門用于創(chuàng)建索引的 CREATE INDEX 語(yǔ)句在一個(gè)已有的表上創(chuàng)建索引,但該語(yǔ)句不能創(chuàng)建主鍵啥么。
語(yǔ)法格式:
CREATE <索引名> ON <表名> (<列名> [<長(zhǎng)度>] [ ASC | DESC])
語(yǔ)法說明如下:
-
<索引名>
:指定索引名登舞。一個(gè)表可以創(chuàng)建多個(gè)索引,但每個(gè)索引在該表中的名稱是唯一的悬荣。 -
<表名>
:指定要?jiǎng)?chuàng)建索引的表名逊躁。 -
<列名>
:指定要?jiǎng)?chuàng)建索引的列名。通秤缥酰可以考慮將查詢語(yǔ)句中在 JOIN 子句和 WHERE 子句里經(jīng)常出現(xiàn)的列作為索引列稽煤。 -
<長(zhǎng)度>
:可選項(xiàng)。指定使用列前的 length 個(gè)字符來創(chuàng)建索引囚戚。使用列的一部分創(chuàng)建索引有利于減小索引文件的大小酵熙,節(jié)省索引列所占的空間。在某些情況下驰坊,只能對(duì)列的前綴進(jìn)行索引匾二。索引列的長(zhǎng)度有一個(gè)最大上限 255 個(gè)字節(jié)(MyISAM 和 InnoDB 表的最大上限為 1000 個(gè)字節(jié)),如果索引列的長(zhǎng)度超過了這個(gè)上限拳芙,就只能用列的前綴進(jìn)行索引察藐。另外,BLOB 或 TEXT 類型的列也必須使用前綴索引舟扎。 -
ASC|DESC
:可選項(xiàng)分飞。ASC
指定索引按照升序來排列,DESC
指定索引按照降序來排列睹限,默認(rèn)為ASC
譬猫。
使用 CREATE TABLE 語(yǔ)句
索引也可以在創(chuàng)建表(CREATE TABLE)的同時(shí)創(chuàng)建。在 CREATE TABLE 語(yǔ)句中添加以下語(yǔ)句羡疗。語(yǔ)法格式:
CONSTRAINT PRIMARY KEY [索引類型] (<列名>,…)
在 CREATE TABLE 語(yǔ)句中添加此語(yǔ)句染服,表示在創(chuàng)建新表的同時(shí)創(chuàng)建該表的主鍵。
語(yǔ)法格式:
KEY | INDEX [<索引名>] [<索引類型>] (<列名>,…)
在 CREATE TABLE 語(yǔ)句中添加此語(yǔ)句叨恨,表示在創(chuàng)建新表的同時(shí)創(chuàng)建該表的索引柳刮。
語(yǔ)法格式:
UNIQUE [ INDEX | KEY] [<索引名>] [<索引類型>] (<列名>,…)
在 CREATE TABLE 語(yǔ)句中添加此語(yǔ)句,表示在創(chuàng)建新表的同時(shí)創(chuàng)建該表的唯一性索引痒钝。
語(yǔ)法格式:
FOREIGN KEY <索引名> <列名>
在 CREATE TABLE 語(yǔ)句中添加此語(yǔ)句秉颗,表示在創(chuàng)建新表的同時(shí)創(chuàng)建該表的外鍵。
在使用 CREATE TABLE 語(yǔ)句定義列選項(xiàng)的時(shí)候午乓,可以通過直接在某個(gè)列定義后面添加 PRIMARY KEY 的方式創(chuàng)建主鍵站宗。而當(dāng)主鍵是由多個(gè)列組成的多列索引時(shí),則不能使用這種方法益愈,只能用在語(yǔ)句的最后加上一個(gè) PRIMARY KRY(<列名>梢灭,…) 子句的方式來實(shí)現(xiàn)。
使用 ALTER TABLE 語(yǔ)句
CREATE INDEX 語(yǔ)句可以在一個(gè)已有的表上創(chuàng)建索引蒸其,ALTER TABLE 語(yǔ)句也可以在一個(gè)已有的表上創(chuàng)建索引敏释。在使用 ALTER TABLE 語(yǔ)句修改表的同時(shí),可以向已有的表添加索引摸袁。具體的做法是在 ALTER TABLE 語(yǔ)句中添加以下語(yǔ)法成分的某一項(xiàng)或幾項(xiàng)钥顽。
語(yǔ)法格式:
ADD INDEX [<索引名>] [<索引類型>] (<列名>,…)
在 ALTER TABLE 語(yǔ)句中添加此語(yǔ)法成分,表示在修改表的同時(shí)為該表添加索引靠汁。
語(yǔ)法格式:
ADD PRIMARY KEY [<索引類型>] (<列名>,…)
在 ALTER TABLE 語(yǔ)句中添加此語(yǔ)法成分蜂大,表示在修改表的同時(shí)為該表添加主鍵闽铐。
語(yǔ)法格式:
ADD UNIQUE [ INDEX | KEY] [<索引名>] [<索引類型>] (<列名>,…)
在 ALTER TABLE 語(yǔ)句中添加此語(yǔ)法成分,表示在修改表的同時(shí)為該表添加唯一性索引奶浦。
語(yǔ)法格式:
ADD FOREIGN KEY [<索引名>] (<列名>,…)
在 ALTER TABLE 語(yǔ)句中添加此語(yǔ)法成分兄墅,表示在修改表的同時(shí)為該表添加外鍵。
創(chuàng)建普通索引
創(chuàng)建普通索引時(shí)澳叉,通常使用 INDEX 關(guān)鍵字隙咸。
例子:創(chuàng)建一個(gè)表 tb_stu_info,在該表的 height 字段創(chuàng)建普通索引成洗。輸入的 SQL 語(yǔ)句和執(zhí)行過程如下所示五督。
mysql> CREATE TABLE tb_stu_info
-> (
-> id INT NOT NULL,
-> name CHAR(45) DEFAULT NULL,
-> dept_id INT DEFAULT NULL,
-> age INT DEFAULT NULL,
-> height INT DEFAULT NULL,
-> INDEX(height)
-> );
Query OK,0 rows affected (0.40 sec)
mysql> SHOW CREATE TABLE tb_stu_info\G
*************************** 1. row ***************************
Table: tb_stu_info
Create Table: CREATE TABLE `tb_stu_info` (
`id` int(11) NOT NULL,
`name` char(45) DEFAULT NULL,
`dept_id` int(11) DEFAULT NULL,
`age` int(11) DEFAULT NULL,
`height` int(11) DEFAULT NULL,
KEY `height` (`height`)
) ENGINE=InnoDB DEFAULT CHARSET=gb2312
1 row in set (0.01 sec)
創(chuàng)建唯一索引
創(chuàng)建唯一索引瓶殃,通常使用 UNIQUE 參數(shù)充包。
例子:創(chuàng)建一個(gè)表 tb_stu_info2,在該表的 id 字段上使用 UNIQUE 關(guān)鍵字創(chuàng)建唯一索引碌燕。輸入的 SQL 語(yǔ)句和執(zhí)行過程如下所示误证。
mysql> CREATE TABLE tb_stu_info2
-> (
-> id INT NOT NULL,
-> name CHAR(45) DEFAULT NULL,
-> dept_id INT DEFAULT NULL,
-> age INT DEFAULT NULL,
-> height INT DEFAULT NULL,
-> UNIQUE INDEX(height)
-> );
Query OK,0 rows affected (0.40 sec)
mysql> SHOW CREATE TABLE tb_stu_info2\G
*************************** 1. row ***************************
Table: tb_stu_info2
Create Table: CREATE TABLE `tb_stu_info2` (
`id` int(11) NOT NULL,
`name` char(45) DEFAULT NULL,
`dept_id` int(11) DEFAULT NULL,
`age` int(11) DEFAULT NULL,
`height` int(11) DEFAULT NULL,
UNIQUE KEY `height` (`height`)
) ENGINE=InnoDB DEFAULT CHARSET=gb2312
1 row in set (0.00 sec)
MySQL查看索引
索引創(chuàng)建完成后修壕,可以利用 SQL 語(yǔ)句查看已經(jīng)存在的索引愈捅。在 MySQL 中,可以使用 SHOW INDEX 語(yǔ)句查看表中創(chuàng)建的索引慈鸠。
查看索引的語(yǔ)法格式如下:
SHOW INDEX FROM <表名> [ FROM <數(shù)據(jù)庫(kù)名>]
語(yǔ)法說明如下:
- <表名>:指定需要查看索引的數(shù)據(jù)表名蓝谨。
- <數(shù)據(jù)庫(kù)名>:指定需要查看索引的數(shù)據(jù)表所在的數(shù)據(jù)庫(kù),可省略青团。比如譬巫,SHOW INDEX FROM student FROM test; 語(yǔ)句表示查看 test 數(shù)據(jù)庫(kù)中 student 數(shù)據(jù)表的索引。
其中各主要參數(shù)說明如下:
參數(shù) | 說明 |
---|---|
Table | 表示創(chuàng)建索引的數(shù)據(jù)表名督笆,這里是 tb_stu_info2 數(shù)據(jù)表芦昔。 |
Non_unique | 表示該索引是否是唯一索引。若不是唯一索引娃肿,則該列的值為 1咕缎;若是唯一索引,則該列的值為 0料扰。 |
Key_name | 表示索引的名稱凭豪。 |
Seq_in_index | 表示該列在索引中的位置,如果索引是單列的,則該列的值為 1;如果索引是組合索引氓仲,則該列的值為每列在索引定義中的順序由蘑。 |
Column_name | 表示定義索引的列字段。 |
Collation | 表示列以何種順序存儲(chǔ)在索引中梢薪。在 MySQL 中耻讽,升序顯示值“A”(升序)有决,若顯示為 NULL拼余,則表示無(wú)分類郑趁。 |
Cardinality | 索引中唯一值數(shù)目的估計(jì)值∽怂眩基數(shù)根據(jù)被存儲(chǔ)為整數(shù)的統(tǒng)計(jì)數(shù)據(jù)計(jì)數(shù),所以即使對(duì)于小型表捆憎,該值也沒有必要是精確的舅柜。基數(shù)越大躲惰,當(dāng)進(jìn)行聯(lián)合時(shí)致份,MySQL 使用該索引的機(jī)會(huì)就越大。 |
Sub_part | 表示列中被編入索引的字符的數(shù)量础拨。若列只是部分被編入索引氮块,則該列的值為被編入索引的字符的數(shù)目;若整列被編入索引诡宗,則該列的值為 NULL滔蝉。 |
Packed | 指示關(guān)鍵字如何被壓縮。若沒有被壓縮塔沃,值為 NULL蝠引。 |
Null | 用于顯示索引列中是否包含 NULL。若列含有 NULL蛀柴,該列的值為 YES螃概。若沒有,則該列的值為 NO鸽疾。 |
Index_type | 顯示索引使用的類型和方法(BTREE吊洼、FULLTEXT、HASH制肮、RTREE)冒窍。 |
Comment | 顯示評(píng)注。 |
MySQL修改和刪除索引
刪除索引是指將表中已經(jīng)存在的索引刪除掉弄企。不用的索引建議進(jìn)行刪除超燃,因?yàn)樗鼈儠?huì)降低表的更新速度,影響數(shù)據(jù)庫(kù)的性能拘领。對(duì)于這樣的索引意乓,應(yīng)該將其刪除。
在 MySQL 中修改索引可以通過刪除原索引,再根據(jù)需要?jiǎng)?chuàng)建一個(gè)同名的索引届良,從而實(shí)現(xiàn)修改索引的操作笆凌。
基本語(yǔ)法
當(dāng)不再需要索引時(shí),可以使用 DROP INDEX 語(yǔ)句或 ALTER TABLE 語(yǔ)句來對(duì)索引進(jìn)行刪除士葫。
使用 DROP INDEX 語(yǔ)句
語(yǔ)法格式:
DROP INDEX <索引名> ON <表名>
語(yǔ)法說明如下:
-
<索引名>
:要?jiǎng)h除的索引名乞而。 -
<表名>
:指定該索引所在的表名。
使用 ALTER TABLE 語(yǔ)句
根據(jù) ALTER TABLE 語(yǔ)句的語(yǔ)法可知慢显,該語(yǔ)句也可以用于刪除索引爪模。具體使用方法是將 ALTER TABLE 語(yǔ)句的語(yǔ)法中部分指定為以下子句中的某一項(xiàng)。
- DROP PRIMARY KEY:表示刪除表中的主鍵荚藻。一個(gè)表只有一個(gè)主鍵屋灌,主鍵也是一個(gè)索引。
- DROP INDEX index_name:表示刪除名稱為 index_name 的索引应狱。
- DROP FOREIGN KEY fk_symbol:表示刪除外鍵共郭。
注意:如果刪除的列是索引的組成部分,那么在刪除該列時(shí)疾呻,也會(huì)將該列從索引中刪除除嘹;如果組成索引的所有列都被刪除,那么整個(gè)索引將被刪除岸蜗。
索引失效
索引可以提高查詢的速度尉咕,但并不是使用帶有索引的字段查詢時(shí),索引都會(huì)起作用散吵。使用索引有幾種特殊情況龙考,在這些情況下,有可能使用帶有索引的字段查詢時(shí)矾睦,索引并沒有起作用晦款,下面重點(diǎn)介紹這幾種特殊情況。
- 查詢語(yǔ)句中使用LIKE關(guān)鍵字:在查詢語(yǔ)句中使用 LIKE 關(guān)鍵字進(jìn)行查詢時(shí)枚冗,如果匹配字符串的第一個(gè)字符為“%”缓溅,索引不會(huì)被使用。如果“%”不是在第一個(gè)位置赁温,索引就會(huì)被使用坛怪。
- 查詢語(yǔ)句中使用多列索引:多列索引是在表的多個(gè)字段上創(chuàng)建一個(gè)索引,只有查詢條件中使用了這些字段中的第一個(gè)字段股囊,索引才會(huì)被使用袜匿。
- 查詢語(yǔ)句中使用OR關(guān)鍵字:查詢語(yǔ)句只有 OR 關(guān)鍵字時(shí),如果 OR 前后的兩個(gè)條件的列都是索引稚疹,那么查詢中將使用索引居灯。如果 OR 前后有一個(gè)條件的列不是索引,那么查詢中將不使用索引。
MySQL索引的設(shè)計(jì)原則
索引的設(shè)計(jì)可以遵循一些已有的原則怪嫌,創(chuàng)建索引的時(shí)候應(yīng)盡量考慮符合這些原則义锥,便于提升索引的使用效率,更高效的使用索引岩灭。
-
選擇唯一性索引:唯一性索引的值是唯一的拌倍,可以更快速的通過該索引來確定某條記錄。
- 例如噪径,學(xué)生表中學(xué)號(hào)是具有唯一性的字段柱恤。為該字段建立唯一性索引可以很快的確定某個(gè)學(xué)生的信息。如果使用姓名的話找爱,可能存在同名現(xiàn)象膨更,從而降低查詢速度。
- 為經(jīng)常需要排序缴允、分組和聯(lián)合操作的字段建立索引:經(jīng)常需要 ORDER BY、GROUP BY珍德、DISTINCT 和 UNION 等操作的字段练般,排序操作會(huì)浪費(fèi)很多時(shí)間。如果為其建立索引锈候,可以有效地避免排序操作薄料。
-
為常作為查詢條件的字段建立索引:如果某個(gè)字段經(jīng)常用來做查詢條件,那么該字段的查詢速度會(huì)影響整個(gè)表的查詢速度泵琳。因此摄职,為這樣的字段建立索引,可以提高整個(gè)表的查詢速度获列。
- 注意:常查詢條件的字段不一定是所要選擇的列谷市,換句話說,最適合索引的列是出現(xiàn)在 WHERE 子句中的列击孩,或連接子句中指定的列迫悠,而不是出現(xiàn)在 SELECT 關(guān)鍵字后的選擇列表中的列。
-
限制索引的數(shù)目:索引的數(shù)目不是“越多越好”巩梢。每個(gè)索引都需要占用磁盤空間创泄,索引越多,需要的磁盤空間就越大括蝠。在修改表的內(nèi)容時(shí)鞠抑,索引必須進(jìn)行更新,有時(shí)還可能需要重構(gòu)忌警。因此搁拙,索引越多,更新表的時(shí)間就越長(zhǎng)。
- 如果有一個(gè)索引很少利用或從不使用感混,那么會(huì)不必要地減緩表的修改速度端幼。此外,MySQL 在生成一個(gè)執(zhí)行計(jì)劃時(shí)弧满,要考慮各個(gè)索引婆跑,這也要花費(fèi)時(shí)間。創(chuàng)建多余的索引給查詢優(yōu)化帶來了更多的工作庭呜。索引太多滑进,也可能會(huì)使 MySQL 選擇不到所要使用的最佳索引。
-
盡量使用數(shù)據(jù)量少的索引:如果索引的值很長(zhǎng)募谎,那么查詢的速度會(huì)受到影響扶关。
- 例如,對(duì)一個(gè) CHAR(100) 類型的字段進(jìn)行全文檢索需要的時(shí)間肯定要比對(duì) CHAR(10) 類型的字段需要的時(shí)間要多数冬。
- 數(shù)據(jù)量小的表最好不要使用索引:由于數(shù)據(jù)較小节槐,查詢花費(fèi)的時(shí)間可能比遍歷索引的時(shí)間還要短,索引可能不會(huì)產(chǎn)生優(yōu)化效果拐纱。
-
盡量使用前綴來索引:如果索引字段的值很長(zhǎng)铜异,最好使用值的前綴來索引。
- 例如秸架,TEXT 和 BLOG 類型的字段揍庄,進(jìn)行全文檢索會(huì)很浪費(fèi)時(shí)間。如果只檢索字段的前面的若干個(gè)字符东抹,這樣可以提高檢索速度蚂子。
- 刪除不再使用或者很少使用的索引:表中的數(shù)據(jù)被大量更新,或者數(shù)據(jù)的使用方式被改變后缭黔,原有的一些索引可能不再需要食茎。應(yīng)該定期找出這些索引,將它們刪除馏谨,從而減少索引對(duì)更新操作的影響董瞻。
總結(jié):選擇索引的最終目的是為了使查詢的速度變快,上面給出的原則是最基本的準(zhǔn)則田巴,但不能只拘泥于上面的準(zhǔn)則钠糊。應(yīng)該在學(xué)習(xí)和工作中不斷的實(shí)踐,根據(jù)應(yīng)用的實(shí)際情況進(jìn)行分析和判斷壹哺,選擇最合適的索引方式抄伍。
存儲(chǔ)過程是什么
在數(shù)據(jù)庫(kù)的實(shí)際操作中,經(jīng)常會(huì)有需要多條 SQL 語(yǔ)句處理多個(gè)表才能完成的操作管宵。
- 例如截珍,為了確認(rèn)學(xué)生能否畢業(yè)攀甚,需要同時(shí)查詢學(xué)生檔案表、成績(jī)表和綜合表岗喉,此時(shí)就需要使用多條 SQL 語(yǔ)句來針對(duì)這幾個(gè)數(shù)據(jù)表完成處理要求秋度。
存儲(chǔ)過程是一組為了完成特定功能的 SQL 語(yǔ)句集合。使用存儲(chǔ)過程的目的是將常用或復(fù)雜的工作預(yù)先用 SQL 語(yǔ)句寫好并用一個(gè)指定名稱存儲(chǔ)起來钱床,這個(gè)過程經(jīng)編譯和優(yōu)化后存儲(chǔ)在數(shù)據(jù)庫(kù)服務(wù)器中荚斯,因此稱為存儲(chǔ)過程。當(dāng)以后需要數(shù)據(jù)庫(kù)提供與已定義好的存儲(chǔ)過程的功能相同的服務(wù)時(shí)查牌,只需調(diào)用“CALL存儲(chǔ)過程名字”即可自動(dòng)完成事期。
常用操作數(shù)據(jù)庫(kù)的 SQL 語(yǔ)句在執(zhí)行的時(shí)候需要先編譯,然后執(zhí)行纸颜。存儲(chǔ)過程則采用另一種方式來執(zhí)行 SQL 語(yǔ)句兽泣。
一個(gè)存儲(chǔ)過程是一個(gè)可編程的函數(shù),它在數(shù)據(jù)庫(kù)中創(chuàng)建并保存胁孙,一般由 SQL 語(yǔ)句和一些特殊的控制結(jié)構(gòu)組成唠倦。當(dāng)希望在不同的應(yīng)用程序或平臺(tái)上執(zhí)行相同的特定功能時(shí),存儲(chǔ)過程尤為合適涮较。
MySQL 5.0 版本以前并不支持存儲(chǔ)過程牵敷,這使 MySQL 在應(yīng)用上大打折扣。MySQL 從 5.0 版本開始支持存儲(chǔ)過程法希,既提高了數(shù)據(jù)庫(kù)的處理速度,同時(shí)也提高了數(shù)據(jù)庫(kù)編程的靈活性
存儲(chǔ)過程是數(shù)據(jù)庫(kù)中的一個(gè)重要功能靶瘸,存儲(chǔ)過程可以用來轉(zhuǎn)換數(shù)據(jù)苫亦、數(shù)據(jù)遷移、制作報(bào)表怨咪,它類似于編程語(yǔ)言屋剑,一次執(zhí)行成功,就可以隨時(shí)被調(diào)用诗眨,完成指定的功能操作唉匾。
使用存儲(chǔ)過程不僅可以提高數(shù)據(jù)庫(kù)的訪問效率,同時(shí)也可以提高數(shù)據(jù)庫(kù)使用的安全性匠楚。
對(duì)于調(diào)用者來說巍膘,存儲(chǔ)過程封裝了 SQL 語(yǔ)句,調(diào)用者無(wú)需考慮邏輯功能的具體實(shí)現(xiàn)過程芋簿。只是簡(jiǎn)單調(diào)用即可峡懈,它可以被 Java 和 C# 等編程語(yǔ)言調(diào)用。
編寫存儲(chǔ)過程對(duì)開發(fā)者要求稍微高一些与斤,但這并不影響存儲(chǔ)過程的普遍使用肪康,因?yàn)榇鎯?chǔ)過程有如下優(yōu)點(diǎn):
- 封裝性:通常完成一個(gè)邏輯功能需要多條 SQL 語(yǔ)句荚恶,而且各個(gè)語(yǔ)句之間很可能傳遞參數(shù),所以磷支,編寫邏輯功能相對(duì)來說稍微復(fù)雜些谒撼,而存儲(chǔ)過程可以把這些 SQL 語(yǔ)句包含到一個(gè)獨(dú)立的單元中,使外界看不到復(fù)雜的 SQL 語(yǔ)句雾狈,只需要簡(jiǎn)單調(diào)用即可達(dá)到目的廓潜。并且數(shù)據(jù)庫(kù)專業(yè)人員可以隨時(shí)對(duì)存儲(chǔ)過程進(jìn)行修改,而不會(huì)影響到調(diào)用它的應(yīng)用程序源代碼箍邮。
- 可增強(qiáng) SQL 語(yǔ)句的功能和靈活性:存儲(chǔ)過程可以用流程控制語(yǔ)句編寫茉帅,有很強(qiáng)的靈活性,可以完成復(fù)雜的判斷和較復(fù)雜的運(yùn)算锭弊。
- 可減少網(wǎng)絡(luò)流量:由于存儲(chǔ)過程是在服務(wù)器端運(yùn)行的堪澎,且執(zhí)行速度快,因此當(dāng)客戶計(jì)算機(jī)上調(diào)用該存儲(chǔ)過程時(shí)味滞,網(wǎng)絡(luò)中傳送的只是該調(diào)用語(yǔ)句樱蛤,從而可降低網(wǎng)絡(luò)負(fù)載。
- 高性能:當(dāng)存儲(chǔ)過程被成功編譯后剑鞍,就存儲(chǔ)在數(shù)據(jù)庫(kù)服務(wù)器里了昨凡,以后客戶端可以直接調(diào)用,這樣所有的 SQL 語(yǔ)句將從服務(wù)器執(zhí)行蚁署,從而提高性能便脊。但需要說明的是,存儲(chǔ)過程不是越多越好光戈,過多的使用存儲(chǔ)過程反而影響系統(tǒng)性能哪痰。
- 提高數(shù)據(jù)庫(kù)的安全性和數(shù)據(jù)的完整性:存儲(chǔ)過程提高安全性的一個(gè)方案就是把它作為中間組件,存儲(chǔ)過程里可以對(duì)某些表做相關(guān)操作久妆,然后存儲(chǔ)過程作為接口提供給外部程序晌杰。這樣,外部程序無(wú)法直接操作數(shù)據(jù)庫(kù)表筷弦,只能通過存儲(chǔ)過程來操作對(duì)應(yīng)的表肋演,因此在一定程度上,安全性是可以得到提高的烂琴。
- 使數(shù)據(jù)獨(dú)立:數(shù)據(jù)的獨(dú)立可以達(dá)到解耦的效果爹殊,也就是說,程序可以調(diào)用存儲(chǔ)過程奸绷,來替代執(zhí)行多條的 SQL 語(yǔ)句边灭。這種情況下,存儲(chǔ)過程把數(shù)據(jù)同用戶隔離開來健盒,優(yōu)點(diǎn)就是當(dāng)數(shù)據(jù)表的結(jié)構(gòu)改變時(shí)绒瘦,調(diào)用表不用修改程序称簿,只需要數(shù)據(jù)庫(kù)管理者重新編寫存儲(chǔ)過程即可。
MySQL創(chuàng)建存儲(chǔ)過程
MySQL 存儲(chǔ)過程是一些 SQL 語(yǔ)句的集合惰帽,比如有時(shí)候我們可能需要一大串的 SQL 語(yǔ)句憨降,或者說在編寫 SQL 語(yǔ)句的過程中需要設(shè)置一些變量的值,這個(gè)時(shí)候我們就完全有必要編寫一個(gè)存儲(chǔ)過程该酗。
編寫存儲(chǔ)過程并不是件簡(jiǎn)單的事情授药,但是使用存儲(chǔ)過程可以簡(jiǎn)化操作,且減少冗余的操作步驟呜魄,同時(shí)悔叽,還可以減少操作過程中的失誤,提高效率爵嗅,因此應(yīng)該盡可能的學(xué)會(huì)使用存儲(chǔ)過程娇澎。
下面主要介紹如何創(chuàng)建存儲(chǔ)過程。
可以使用 CREATE PROCEDURE 語(yǔ)句創(chuàng)建存儲(chǔ)過程睹晒,語(yǔ)法格式如下:
CREATE PROCEDURE <過程名> ( [過程參數(shù)[,…] ] ) <過程體>
[過程參數(shù)[,…] ] 格式
[ IN | OUT | INOUT ] <參數(shù)名> <類型>
語(yǔ)法說明如下:
- 過程名:存儲(chǔ)過程的名稱趟庄,默認(rèn)在當(dāng)前數(shù)據(jù)庫(kù)中創(chuàng)建。若需要在特定數(shù)據(jù)庫(kù)中創(chuàng)建存儲(chǔ)過程伪很,則要在名稱前面加上數(shù)據(jù)庫(kù)的名稱戚啥,即 db_name.sp_name。
- 需要注意的是锉试,名稱應(yīng)當(dāng)盡量避免選取與 MySQL 內(nèi)置函數(shù)相同的名稱猫十,否則會(huì)發(fā)生錯(cuò)誤。
- 過程參數(shù):存儲(chǔ)過程的參數(shù)列表呆盖。其中拖云,
<參數(shù)名>
為參數(shù)名,<類型>
為參數(shù)的類型(可以是任何有效的 MySQL 數(shù)據(jù)類型)。當(dāng)有多個(gè)參數(shù)時(shí),參數(shù)列表中彼此間用逗號(hào)分隔辈挂。存儲(chǔ)過程可以沒有參數(shù)(此時(shí)存儲(chǔ)過程的名稱后仍需加上一對(duì)括號(hào))抓督,也可以有 1 個(gè)或多個(gè)參數(shù)。- MySQL 存儲(chǔ)過程支持三種類型的參數(shù)邑贴,即輸入?yún)?shù)席里、輸出參數(shù)和輸入/輸出參數(shù),分別用 IN拢驾、OUT 和 INOUT 三個(gè)關(guān)鍵字標(biāo)識(shí)奖磁。其中,輸入?yún)?shù)可以傳遞給一個(gè)存儲(chǔ)過程繁疤,輸出參數(shù)用于存儲(chǔ)過程需要返回一個(gè)操作結(jié)果的情形咖为,而輸入/輸出參數(shù)既可以充當(dāng)輸入?yún)?shù)也可以充當(dāng)輸出參數(shù)秕狰。
- 需要注意的是,參數(shù)的取名不要與數(shù)據(jù)表的列名相同躁染,否則盡管不會(huì)返回出錯(cuò)信息鸣哀,但是存儲(chǔ)過程的 SQL 語(yǔ)句會(huì)將參數(shù)名看作列名,從而引發(fā)不可預(yù)知的結(jié)果吞彤。
- 過程體存儲(chǔ)過程的主體部分我衬,也稱為存儲(chǔ)過程體,包含在過程調(diào)用的時(shí)候必須執(zhí)行的 SQL 語(yǔ)句饰恕。這個(gè)部分以關(guān)鍵字 BEGIN 開始挠羔,以關(guān)鍵字 END 結(jié)束。若存儲(chǔ)過程體中只有一條 SQL 語(yǔ)句埋嵌,則可以省略 BEGIN-END 標(biāo)志破加。
DELIMITER 命令
在存儲(chǔ)過程的創(chuàng)建中,經(jīng)常會(huì)用到一個(gè)十分重要的 MySQL 命令莉恼,即 DELIMITER 命令
在 MySQL 中拌喉,服務(wù)器處理 SQL 語(yǔ)句默認(rèn)是以分號(hào)作為語(yǔ)句結(jié)束標(biāo)志的。然而俐银,在創(chuàng)建存儲(chǔ)過程時(shí)尿背,存儲(chǔ)過程體可能包含有多條 SQL 語(yǔ)句,這些 SQL 語(yǔ)句如果仍以分號(hào)作為語(yǔ)句結(jié)束符捶惜,那么 MySQL 服務(wù)器在處理時(shí)會(huì)以遇到的第一條 SQL 語(yǔ)句結(jié)尾處的分號(hào)作為整個(gè)程序的結(jié)束符田藐,而不再去處理存儲(chǔ)過程體中后面的 SQL 語(yǔ)句,這樣顯然不行吱七。
為解決以上問題汽久,通常使用 DELIMITER 命令將結(jié)束命令修改為其他字符。語(yǔ)法格式如下:
DELIMITER $$
語(yǔ)法說明如下:
- $$ 是用戶定義的結(jié)束符踊餐,通常這個(gè)符號(hào)可以是一些特殊的符號(hào)景醇,如兩個(gè)“?”或兩個(gè)“¥”等。
- 當(dāng)使用 DELIMITER 命令時(shí)吝岭,應(yīng)該避免使用反斜杠“\”字符三痰,因?yàn)樗?MySQL 的轉(zhuǎn)義字符。
在 MySQL 命令行客戶端輸入如下 SQL 語(yǔ)句窜管。
mysql > DELIMITER ??
成功執(zhí)行這條 SQL 語(yǔ)句后散劫,任何命令、語(yǔ)句或程序的結(jié)束標(biāo)志就換為兩個(gè)問號(hào)“??”了幕帆。
若希望換回默認(rèn)的分號(hào)“;”作為結(jié)束標(biāo)志获搏,則在 MySQL 命令行客戶端輸入下列語(yǔ)句即可:
mysql > DELIMITER ;
注意:DELIMITER 和分號(hào)“;”之間一定要有一個(gè)空格。在創(chuàng)建存儲(chǔ)過程時(shí)失乾,必須具有 CREATE ROUTINE 權(quán)限常熙。
MySQL查看存儲(chǔ)過程
創(chuàng)建好存儲(chǔ)過程后纬乍,用戶可以通過 SHOW ATATUS 語(yǔ)句來查看存儲(chǔ)過程的狀態(tài),也可以通過 SHOW CREATE 語(yǔ)句來查看存儲(chǔ)過程的定義症概。
查看存儲(chǔ)過程的狀態(tài)
MySQL 中可以通過 SHOW STATUS 語(yǔ)句查看存儲(chǔ)過程的狀態(tài)蕾额,其基本語(yǔ)法形式如下:
SHOW PROCEDURE STATUS LIKE 存儲(chǔ)過程名;
LIKE 存儲(chǔ)過程名
用來匹配存儲(chǔ)過程的名稱,LIKE 不能省略彼城。
查看存儲(chǔ)過程的定義
MySQL 中可以通過 SHOW CREATE 語(yǔ)句查看存儲(chǔ)過程的狀態(tài)诅蝶,語(yǔ)法格式如下:
SHOW CREATE PROCEDURE 存儲(chǔ)過程名;
SHOW STATUS 語(yǔ)句只能查看存儲(chǔ)過程是操作的哪一個(gè)數(shù)據(jù)庫(kù)、存儲(chǔ)過程的名稱募壕、類型调炬、誰(shuí)定義的、創(chuàng)建和修改時(shí)間舱馅、字符編碼等信息缰泡。但是,這個(gè)語(yǔ)句不能查詢存儲(chǔ)過程的集體定義代嗤,如果需要查看詳細(xì)定義棘钞,需要使用 SHOW CREATE 語(yǔ)句。
存儲(chǔ)過程的信息都存儲(chǔ)在 information_schema 數(shù)據(jù)庫(kù)下的 Routines 表中干毅,可以通過查詢?cè)摫淼挠涗泚聿樵兇鎯?chǔ)過程的信息宜猜,SQL 語(yǔ)句如下:
SELECT * FROM information_schema.Routines WHERE ROUTINE_NAME=存儲(chǔ)過程名;
在 information_schema 數(shù)據(jù)庫(kù)下的 routines 表中,存儲(chǔ)著所有存儲(chǔ)過程的定義硝逢。所以姨拥,使用 SELECT 語(yǔ)句查詢 routines 表中的存儲(chǔ)過程和函數(shù)的定義時(shí),一定要使用 routine_name 字段指定存儲(chǔ)過程的名稱渠鸽,否則叫乌,將查詢出所有的存儲(chǔ)過程的定義。
MySQL修改存儲(chǔ)過程
在實(shí)際開發(fā)過程中徽缚,業(yè)務(wù)需求修改的情況時(shí)有發(fā)生憨奸,所以修改 MySQL 中的存儲(chǔ)過程是不可避免的。
MySQL 中通過 ALTER PROCEDURE 語(yǔ)句來修改存儲(chǔ)過程凿试。
MySQL 中修改存儲(chǔ)過程的語(yǔ)法格式如下:
ALTER PROCEDURE 存儲(chǔ)過程名 [ 特征 ... ]
特征
指定了存儲(chǔ)過程的特性排宰,可能的取值有:
- CONTAINS SQL 表示子程序包含 SQL 語(yǔ)句,但不包含讀或?qū)憯?shù)據(jù)的語(yǔ)句红省。
- NO SQL 表示子程序中不包含 SQL 語(yǔ)句额各。
- READS SQL DATA 表示子程序中包含讀數(shù)據(jù)的語(yǔ)句国觉。
- MODIFIES SQL DATA 表示子程序中包含寫數(shù)據(jù)的語(yǔ)句吧恃。
- SQL SECURITY { DEFINER |INVOKER } 指明誰(shuí)有權(quán)限來執(zhí)行。
- DEFINER 表示只有定義者自己才能夠執(zhí)行麻诀。
- INVOKER 表示調(diào)用者可以執(zhí)行痕寓。
- COMMENT 'string' 表示注釋信息傲醉。
注意:ALTER PROCEDURE 語(yǔ)句用于修改存儲(chǔ)過程的某些特征。如果要修改存儲(chǔ)過程的內(nèi)容呻率,可以先刪除原存儲(chǔ)過程硬毕,再以相同的命名創(chuàng)建新的存儲(chǔ)過程;如果要修改存儲(chǔ)過程的名稱礼仗,可以先刪除原存儲(chǔ)過程吐咳,再以不同的命名創(chuàng)建新的存儲(chǔ)過程。
MySQL刪除存儲(chǔ)過程
存儲(chǔ)過程被創(chuàng)建后元践,就會(huì)一直保存在數(shù)據(jù)庫(kù)服務(wù)器上韭脊,直至被刪除。當(dāng) MySQL 數(shù)據(jù)庫(kù)中存在廢棄的存儲(chǔ)過程時(shí)单旁,我們需要將它從數(shù)據(jù)庫(kù)中刪除沪羔。
MySQL 中使用 DROP PROCEDURE 語(yǔ)句來刪除數(shù)據(jù)庫(kù)中已經(jīng)存在的存儲(chǔ)過程。語(yǔ)法格式如下:
DROP PROCEDURE [ IF EXISTS ] <過程名>
語(yǔ)法說明如下:
- 過程名:指定要?jiǎng)h除的存儲(chǔ)過程的名稱象浑。
- IF EXISTS:指定這個(gè)關(guān)鍵字蔫饰,用于防止因刪除不存在的存儲(chǔ)過程而引發(fā)的錯(cuò)誤。
注意:存儲(chǔ)過程名稱后面沒有參數(shù)列表愉豺,也沒有括號(hào)篓吁,在刪除之前,必須確認(rèn)該存儲(chǔ)過程沒有任何依賴關(guān)系粒氧,否則會(huì)導(dǎo)致其他與之關(guān)聯(lián)的存儲(chǔ)過程無(wú)法運(yùn)行越除。
觸發(fā)器是什么
MySQL 的觸發(fā)器和存儲(chǔ)過程一樣,都是嵌入到 MySQL 中的一段程序外盯,是 MySQL 中管理數(shù)據(jù)的有力工具摘盆。不同的是執(zhí)行存儲(chǔ)過程要使用 CALL 語(yǔ)句來調(diào)用,而觸發(fā)器的執(zhí)行不需要使用 CALL 語(yǔ)句來調(diào)用饱苟,也不需要手工啟動(dòng)孩擂,而是通過對(duì)數(shù)據(jù)表的相關(guān)操作來觸發(fā)、激活從而實(shí)現(xiàn)執(zhí)行箱熬。比如當(dāng)對(duì) student 表進(jìn)行操作(INSERT类垦,DELETE 或 UPDATE)時(shí)就會(huì)激活它執(zhí)行。
觸發(fā)器與數(shù)據(jù)表關(guān)系密切城须,主要用于保護(hù)表中的數(shù)據(jù)蚤认。特別是當(dāng)有多個(gè)表具有一定的相互聯(lián)系的時(shí)候,觸發(fā)器能夠讓不同的表保持?jǐn)?shù)據(jù)的一致性糕伐。
在 MySQL 中砰琢,只有執(zhí)行 INSERT、UPDATE 和 DELETE 操作時(shí)才能激活觸發(fā)器,其它 SQL 語(yǔ)句則不會(huì)激活觸發(fā)器陪汽。
那么為什么要使用觸發(fā)器呢训唱?比如,在實(shí)際開發(fā)項(xiàng)目時(shí)挚冤,我們經(jīng)常會(huì)遇到以下情況:
- 在學(xué)生表中添加一條關(guān)于學(xué)生的記錄時(shí)况增,學(xué)生的總數(shù)就必須同時(shí)改變。
- 增加一條學(xué)生記錄時(shí)训挡,需要檢查年齡是否符合范圍要求澳骤。
- 刪除一條學(xué)生信息時(shí),需要?jiǎng)h除其成績(jī)表上的對(duì)應(yīng)記錄澜薄。
- 刪除一條數(shù)據(jù)時(shí)宴凉,需要在數(shù)據(jù)庫(kù)存檔表中保留一個(gè)備份副本。
雖然上述情況實(shí)現(xiàn)的業(yè)務(wù)邏輯不同表悬,但是它們都需要在數(shù)據(jù)表發(fā)生更改時(shí)弥锄,自動(dòng)進(jìn)行一些處理。這時(shí)就可以使用觸發(fā)器處理蟆沫。
- 例如籽暇,對(duì)于第一種情況,可以創(chuàng)建一個(gè)觸發(fā)器對(duì)象饭庞,每當(dāng)添加一條學(xué)生記錄時(shí)戒悠,就執(zhí)行一次計(jì)算學(xué)生總數(shù)的操作,這樣就可以保證每次添加一條學(xué)生記錄后舟山,學(xué)生總數(shù)和學(xué)生記錄數(shù)是一致的绸狐。
觸發(fā)器的優(yōu)缺點(diǎn)
觸發(fā)器的優(yōu)點(diǎn)如下:
- 觸發(fā)器的執(zhí)行是自動(dòng)的,當(dāng)對(duì)觸發(fā)器相關(guān)表的數(shù)據(jù)做出相應(yīng)的修改后立即執(zhí)行累盗。
- 觸發(fā)器可以實(shí)施比 FOREIGN KEY 約束寒矿、CHECK 約束更為復(fù)雜的檢查和操作。
- 觸發(fā)器可以實(shí)現(xiàn)表數(shù)據(jù)的級(jí)聯(lián)更改若债,在一定程度上保證了數(shù)據(jù)的完整性符相。
觸發(fā)器的缺點(diǎn)如下:
- 使用觸發(fā)器實(shí)現(xiàn)的業(yè)務(wù)邏輯在出現(xiàn)問題時(shí)很難進(jìn)行定位,特別是涉及到多個(gè)觸發(fā)器的情況下蠢琳,會(huì)使后期維護(hù)變得困難啊终。
- 大量使用觸發(fā)器容易導(dǎo)致代碼結(jié)構(gòu)被打亂,增加了程序的復(fù)雜性傲须,
- 如果需要變動(dòng)的數(shù)據(jù)量較大時(shí)蓝牲,觸發(fā)器的執(zhí)行效率會(huì)非常低。
MySQL 支持的觸發(fā)器
在實(shí)際使用中泰讽,MySQL 所支持的觸發(fā)器有三種:INSERT 觸發(fā)器例衍、UPDATE 觸發(fā)器和 DELETE 觸發(fā)器散怖。
INSERT 觸發(fā)器
在 INSERT 語(yǔ)句執(zhí)行之前或之后響應(yīng)的觸發(fā)器。
使用 INSERT 觸發(fā)器需要注意以下幾點(diǎn):
- 在 INSERT 觸發(fā)器代碼內(nèi)肄渗,可引用一個(gè)名為 NEW(不區(qū)分大小寫)的虛擬表來訪問被插入的行。
- 在 BEFORE INSERT 觸發(fā)器中咬最,NEW 中的值也可以被更新翎嫡,即允許更改被插入的值(只要具有對(duì)應(yīng)的操作權(quán)限)。
- 對(duì)于 AUTO_INCREMENT 列永乌,NEW 在 INSERT 執(zhí)行之前包含的值是 0惑申,在 INSERT 執(zhí)行之后將包含新的自動(dòng)生成值。
UPDATE 觸發(fā)器
在 UPDATE 語(yǔ)句執(zhí)行之前或之后響應(yīng)的觸發(fā)器翅雏。
使用 UPDATE 觸發(fā)器需要注意以下幾點(diǎn):
- 在 UPDATE 觸發(fā)器代碼內(nèi)圈驼,可引用一個(gè)名為 NEW(不區(qū)分大小寫)的虛擬表來訪問更新的值。
- 在 UPDATE 觸發(fā)器代碼內(nèi)望几,可引用一個(gè)名為 OLD(不區(qū)分大小寫)的虛擬表來訪問 UPDATE 語(yǔ)句執(zhí)行前的值绩脆。
- 在 BEFORE UPDATE 觸發(fā)器中,NEW 中的值可能也被更新橄抹,即允許更改將要用于 UPDATE 語(yǔ)句中的值(只要具有對(duì)應(yīng)的操作權(quán)限)靴迫。
- OLD 中的值全部是只讀的,不能被更新楼誓。
注意:當(dāng)觸發(fā)器設(shè)計(jì)對(duì)觸發(fā)表自身的更新操作時(shí)玉锌,只能使用 BEFORE 類型的觸發(fā)器,AFTER 類型的觸發(fā)器將不被允許疟羹。
DELETE 觸發(fā)器
在 DELETE 語(yǔ)句執(zhí)行之前或之后響應(yīng)的觸發(fā)器主守。
使用 DELETE 觸發(fā)器需要注意以下幾點(diǎn):
- 在 DELETE 觸發(fā)器代碼內(nèi),可以引用一個(gè)名為 OLD(不區(qū)分大小寫)的虛擬表來訪問被刪除的行榄融。
- OLD 中的值全部是只讀的参淫,不能被更新。
總體來說愧杯,觸發(fā)器使用的過程中黄刚,MySQL 會(huì)按照以下方式來處理錯(cuò)誤。
對(duì)于事務(wù)性表民效,如果觸發(fā)程序失敗憔维,以及由此導(dǎo)致的整個(gè)語(yǔ)句失敗,那么該語(yǔ)句所執(zhí)行的所有更改將回滾畏邢;對(duì)于非事務(wù)性表业扒,則不能執(zhí)行此類回滾,即使語(yǔ)句失敗舒萎,失敗之前所做的任何更改依然有效程储。
若 BEFORE 觸發(fā)程序失敗,則 MySQL 將不執(zhí)行相應(yīng)行上的操作。
若在 BEFORE 或 AFTER 觸發(fā)程序的執(zhí)行過程中出現(xiàn)錯(cuò)誤章鲤,則將導(dǎo)致調(diào)用觸發(fā)程序的整個(gè)語(yǔ)句失敗摊灭。
僅當(dāng) BEFORE 觸發(fā)程序和行操作均已被成功執(zhí)行,MySQL 才會(huì)執(zhí)行 AFTER 觸發(fā)程序败徊。
MySQL創(chuàng)建觸發(fā)器
觸發(fā)器是與 MySQL 數(shù)據(jù)表有關(guān)的數(shù)據(jù)庫(kù)對(duì)象帚呼,在滿足定義條件時(shí)觸發(fā),并執(zhí)行觸發(fā)器中定義的語(yǔ)句集合皱蹦。觸發(fā)器的這種特性可以協(xié)助應(yīng)用在數(shù)據(jù)庫(kù)端確保數(shù)據(jù)的完整性煤杀。
基本語(yǔ)法
在 MySQL 5.7 中,可以使用 CREATE TRIGGER 語(yǔ)句創(chuàng)建觸發(fā)器沪哺。
語(yǔ)法格式如下:
CREATE <觸發(fā)器名> < BEFORE | AFTER >
<INSERT | UPDATE | DELETE >
ON <表名> FOR EACH Row<觸發(fā)器主體>
語(yǔ)法說明如下沈自。
- 觸發(fā)器名:觸發(fā)器的名稱,觸發(fā)器在當(dāng)前數(shù)據(jù)庫(kù)中必須具有唯一的名稱辜妓。如果要在某個(gè)特定數(shù)據(jù)庫(kù)中創(chuàng)建枯途,名稱前面應(yīng)該加上數(shù)據(jù)庫(kù)的名稱。
- INSERT | UPDATE | DELETE:觸發(fā)事件籍滴,用于指定激活觸發(fā)器的語(yǔ)句的種類柔袁。
- 注意:三種觸發(fā)器的執(zhí)行時(shí)間如下。
- INSERT:將新行插入表時(shí)激活觸發(fā)器异逐。例如捶索,INSERT 的 BEFORE 觸發(fā)器不僅能被 MySQL 的 INSERT 語(yǔ)句激活,也能被 LOAD DATA 語(yǔ)句激活灰瞻。
- DELETE: 從表中刪除某一行數(shù)據(jù)時(shí)激活觸發(fā)器腥例,例如 DELETE 和 REPLACE 語(yǔ)句。
- UPDATE:更改表中某一行數(shù)據(jù)時(shí)激活觸發(fā)器酝润,例如 UPDATE 語(yǔ)句燎竖。
- 注意:三種觸發(fā)器的執(zhí)行時(shí)間如下。
- BEFORE | AFTER:BEFORE 和 AFTER,觸發(fā)器被觸發(fā)的時(shí)刻要销,表示觸發(fā)器是在激活它的語(yǔ)句之前或之后觸發(fā)构回。若希望驗(yàn)證新數(shù)據(jù)是否滿足條件,則使用 BEFORE 選項(xiàng)疏咐;若希望在激活觸發(fā)器的語(yǔ)句執(zhí)行之后完成幾個(gè)或更多的改變纤掸,則通常使用 AFTER 選項(xiàng)。
- 表名:與觸發(fā)器相關(guān)聯(lián)的表名浑塞,此表必須是永久性表借跪,不能將觸發(fā)器與臨時(shí)表或視圖關(guān)聯(lián)起來。在該表上觸發(fā)事件發(fā)生時(shí)才會(huì)激活觸發(fā)器酌壕。同一個(gè)表不能擁有兩個(gè)具有相同觸發(fā)時(shí)刻和事件的觸發(fā)器掏愁。例如歇由,對(duì)于一張數(shù)據(jù)表,不能同時(shí)有兩個(gè) BEFORE UPDATE 觸發(fā)器果港,但可以有一個(gè) BEFORE UPDATE 觸發(fā)器和一個(gè) BEFORE INSERT 觸發(fā)器沦泌,或一個(gè) BEFORE UPDATE 觸發(fā)器和一個(gè) AFTER UPDATE 觸發(fā)器。
- 觸發(fā)器主體:觸發(fā)器動(dòng)作主體辛掠,包含觸發(fā)器激活時(shí)將要執(zhí)行的 MySQL 語(yǔ)句谢谦。如果要執(zhí)行多個(gè)語(yǔ)句,可使用 BEGIN…END 復(fù)合語(yǔ)句結(jié)構(gòu)公浪。
- FOR EACH ROW:一般是指行級(jí)觸發(fā),對(duì)于受觸發(fā)事件影響的每一行都要激活觸發(fā)器的動(dòng)作船侧。例如欠气,使用 INSERT 語(yǔ)句向某個(gè)表中插入多行數(shù)據(jù)時(shí),觸發(fā)器會(huì)對(duì)每一行數(shù)據(jù)的插入都執(zhí)行相應(yīng)的觸發(fā)器動(dòng)作镜撩。
注意:每個(gè)表都支持 INSERT预柒、UPDATE 和 DELETE 的 BEFORE 與 AFTER,因此每個(gè)表最多支持 6 個(gè)觸發(fā)器袁梗。每個(gè)表的每個(gè)事件每次只允許有一個(gè)觸發(fā)器宜鸯。單一觸發(fā)器不能與多個(gè)事件或多個(gè)表關(guān)聯(lián)。
另外遮怜,在 MySQL 中淋袖,若需要查看數(shù)據(jù)庫(kù)中已有的觸發(fā)器,則可以使用 SHOW TRIGGERS 語(yǔ)句锯梁。
創(chuàng)建 BEFORE 類型觸發(fā)器
在 test_db 數(shù)據(jù)庫(kù)中即碗,數(shù)據(jù)表 tb_emp8 為員工信息表,包含 id陌凳、name剥懒、deptId 和 salary 字段,數(shù)據(jù)表 tb_emp8 的表結(jié)構(gòu)如下所示合敦。
mysql> SELECT * FROM tb_emp8;
Empty set (0.07 sec)
mysql> DESC tb_emp8;
+--------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------+-------------+------+-----+---------+-------+
| id | int(11) | NO | PRI | NULL | |
| name | varchar(22) | YES | UNI | NULL | |
| deptId | int(11) | NO | MUL | NULL | |
| salary | float | YES | | 0 | |
+--------+-------------+------+-----+---------+-------+
4 rows in set (0.05 sec)
【實(shí)例 1】創(chuàng)建一個(gè)名為 SumOfSalary 的觸發(fā)器初橘,觸發(fā)的條件是向數(shù)據(jù)表 tb_emp8 中插入數(shù)據(jù)之前,對(duì)新插入的 salary 字段值進(jìn)行求和計(jì)算充岛。輸入的 SQL 語(yǔ)句和執(zhí)行過程如下所示保檐。
mysql> CREATE TRIGGER SumOfSalary
-> BEFORE INSERT ON tb_emp8
-> FOR EACH ROW
-> SET @sum=@sum+NEW.salary;
Query OK, 0 rows affected (0.35 sec)
觸發(fā)器 SumOfSalary 創(chuàng)建完成之后,向表 tb_emp8 中插入記錄時(shí)崔梗,定義的 sum 值由 0 變成了 1500澜汤,即插入值 1000 和 500 的和,如下所示得滤。
SET @sum=0;
Query OK, 0 rows affected (0.05 sec)
mysql> INSERT INTO tb_emp8
-> VALUES(1,'A',1,1000),(2,'B',1,500);
Query OK, 2 rows affected (0.09 sec)
Records: 2 Duplicates: 0 Warnings: 0
mysql> SELECT @sum;
+------+
| @sum |
+------+
| 1500 |
+------+
1 row in set (0.03 sec)
創(chuàng)建 AFTER 類型觸發(fā)器
在 test_db 數(shù)據(jù)庫(kù)中,數(shù)據(jù)表 tb_emp6 和 tb_emp7 都為員工信息表爪膊,包含 id、name砸王、deptId 和 salary 字段推盛,數(shù)據(jù)表 tb_emp6 和 tb_emp7 的表結(jié)構(gòu)如下所示。
mysql> SELECT * FROM tb_emp6;
Empty set (0.07 sec)
mysql> SELECT * FROM tb_emp7;
Empty set (0.03 sec)
mysql> DESC tb_emp6;
+--------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------+-------------+------+-----+---------+-------+
| id | int(11) | NO | PRI | NULL | |
| name | varchar(25) | YES | | NULL | |
| deptId | int(11) | YES | MUL | NULL | |
| salary | float | YES | | NULL | |
+--------+-------------+------+-----+---------+-------+
4 rows in set (0.00 sec)
mysql> DESC tb_emp7;
+--------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------+-------------+------+-----+---------+-------+
| id | int(11) | NO | PRI | NULL | |
| name | varchar(25) | YES | | NULL | |
| deptId | int(11) | YES | | NULL | |
| salary | float | YES | | 0 | |
+--------+-------------+------+-----+---------+-------+
4 rows in set (0.04 sec)
【實(shí)例 2】創(chuàng)建一個(gè)名為 double_salary 的觸發(fā)器谦铃,觸發(fā)的條件是向數(shù)據(jù)表 tb_emp6 中插入數(shù)據(jù)之后耘成,再向數(shù)據(jù)表 tb_emp7 中插入相同的數(shù)據(jù),并且 salary 為 tb_emp6 中新插入的 salary 字段值的 2 倍驹闰。輸入的 SQL 語(yǔ)句和執(zhí)行過程如下所示瘪菌。
mysql> CREATE TRIGGER double_salary
-> AFTER INSERT ON tb_emp6
-> FOR EACH ROW
-> INSERT INTO tb_emp7
-> VALUES (NEW.id,NEW.name,deptId,2*NEW.salary);
Query OK, 0 rows affected (0.25 sec)
觸發(fā)器 double_salary 創(chuàng)建完成之后,向表 tb_emp6 中插入記錄時(shí)嘹朗,同時(shí)向表 tb_emp7 中插入相同的記錄师妙,并且 salary 字段為 tb_emp6 中 salary 字段值的 2 倍,如下所示屹培。
mysql> INSERT INTO tb_emp6
-> VALUES (1,'A',1,1000),(2,'B',1,500);
Query OK, 2 rows affected (0.09 sec)
Records: 2 Duplicates: 0 Warnings: 0
mysql> SELECT * FROM tb_emp6;
+----+------+--------+--------+
| id | name | deptId | salary |
+----+------+--------+--------+
| 1 | A | 1 | 1000 |
| 2 | B | 1 | 500 |
+----+------+--------+--------+
3 rows in set (0.04 sec)
mysql> SELECT * FROM tb_emp7;
+----+------+--------+--------+
| id | name | deptId | salary |
+----+------+--------+--------+
| 1 | A | 1 | 2000 |
| 2 | B | 1 | 1000 |
+----+------+--------+--------+
2 rows in set (0.06 sec)
MySQL查看觸發(fā)器
查看觸發(fā)器是指查看數(shù)據(jù)庫(kù)中已經(jīng)存在的觸發(fā)器的定義默穴、狀態(tài)和語(yǔ)法信息等。MySQL 中查看觸發(fā)器的方法包括 SHOW TRIGGERS 語(yǔ)句和查詢 information_schema 數(shù)據(jù)庫(kù)下的 triggers 數(shù)據(jù)表等褪秀。本節(jié)將詳細(xì)介紹這兩種查看觸發(fā)器的方法蓄诽。
SHOW TRIGGERS語(yǔ)句查看觸發(fā)器信息
在 MySQL 中,可以通過 SHOW TRIGGERS 語(yǔ)句來查看觸發(fā)器的基本信息媒吗,語(yǔ)法格式如下:
SHOW TRIGGERS;
對(duì)以上顯示信息的說明如下:
- Trigger 表示觸發(fā)器的名稱仑氛,在這里觸發(fā)器的名稱為 trigupdate;
- Event 表示激活觸發(fā)器的事件闸英,這里的觸發(fā)事件為更新操作 UPDATE调衰;
- Table 表示激活觸發(fā)器的操作對(duì)象表,這里為 account 表自阱;
- Statement 表示觸發(fā)器執(zhí)行的操作嚎莉,這里是向 myevent 數(shù)據(jù)表中插入一條數(shù)據(jù);
- Timing 表示觸發(fā)器觸發(fā)的時(shí)間沛豌,這里為更新操作之后(AFTER)趋箩;
- 還有一些其他信息,比如觸發(fā)器的創(chuàng)建時(shí)間加派、SQL 的模式叫确、觸發(fā)器的定義賬戶和字符集等,這里不再一一介紹芍锦。
SHOW TRIGGERS 語(yǔ)句用來查看當(dāng)前創(chuàng)建的所有觸發(fā)器的信息竹勉。因?yàn)樵撜Z(yǔ)句無(wú)法查詢指定的觸發(fā)器,所以在觸發(fā)器較少的情況下娄琉,使用該語(yǔ)句會(huì)很方便次乓。如果要查看特定觸發(fā)器的信息或者數(shù)據(jù)庫(kù)中觸發(fā)器較多時(shí)吓歇,可以直接從 information_schema 數(shù)據(jù)庫(kù)中的 triggers 數(shù)據(jù)表中查找。
在triggers表中查看觸發(fā)器信息
在 MySQL 中票腰,所有觸發(fā)器的信息都存在 information_schema 數(shù)據(jù)庫(kù)的 triggers 表中城看,可以通過查詢命令 SELECT 來查看,具體的語(yǔ)法如下:
SELECT * FROM information_schema.triggers WHERE trigger_name= '觸發(fā)器名';
其中杏慰,'觸發(fā)器名'
用來指定要查看的觸發(fā)器的名稱测柠,需要用單引號(hào)引起來。這種方式可以查詢指定的觸發(fā)器缘滥,使用起來更加方便轰胁、靈活。
示例 2
下面使用 SELECT 命令查看 trigupdate 觸發(fā)器朝扼,SQL 語(yǔ)句如下:
SELECT * FROM information_schema.triggers WHERE TRIGGER_NAME= 'trigupdate'\G
顯示信息的說明如下:
- TRIGGER_SCHEMA 表示觸發(fā)器所在的數(shù)據(jù)庫(kù)赃阀;
- TRIGGER_NAME 表示觸發(fā)器的名稱;
- EVENT_OBJECT_TABLE 表示在哪個(gè)數(shù)據(jù)表上觸發(fā)吟税;
- ACTION_STATEMENT 表示觸發(fā)器觸發(fā)的時(shí)候執(zhí)行的具體操作凹耙;
- ACTION_ORIENTATION 的值為 ROW姿现,表示在每條記錄上都觸發(fā)肠仪;
- ACTION_TIMING 表示觸發(fā)的時(shí)刻是 AFTER;
- 還有一些其他信息备典,比如觸發(fā)器的創(chuàng)建時(shí)間异旧、SQL 的模式、觸發(fā)器的定義賬戶和字符集等提佣,這里不再一一介紹吮蛹。
上述 SQL 語(yǔ)句也可以不指定觸發(fā)器名稱,這樣將查看所有的觸發(fā)器拌屏,SQL 語(yǔ)句如下:
SELECT * FROM information_schema.triggers \G
這個(gè)語(yǔ)句會(huì)顯示 triggers 數(shù)據(jù)表中所有的觸發(fā)器信息潮针。
MySQL修改和刪除觸發(fā)器
修改觸發(fā)器可以通過刪除原觸發(fā)器,再以相同的名稱創(chuàng)建新的觸發(fā)器倚喂。
基本語(yǔ)法
與其他 MySQL 數(shù)據(jù)庫(kù)對(duì)象一樣每篷,可以使用 DROP 語(yǔ)句將觸發(fā)器從數(shù)據(jù)庫(kù)中刪除。
語(yǔ)法格式如下:
DROP TRIGGER [ IF EXISTS ] [數(shù)據(jù)庫(kù)名] <觸發(fā)器名>
語(yǔ)法說明如下:
- 觸發(fā)器名:要?jiǎng)h除的觸發(fā)器名稱端圈。
- 數(shù)據(jù)庫(kù)名:可選項(xiàng)焦读。指定觸發(fā)器所在的數(shù)據(jù)庫(kù)的名稱。若沒有指定舱权,則為當(dāng)前默認(rèn)的數(shù)據(jù)庫(kù)矗晃。
- 權(quán)限:執(zhí)行 DROP TRIGGER 語(yǔ)句需要 SUPER 權(quán)限。
- IF EXISTS:可選項(xiàng)宴倍。避免在沒有觸發(fā)器的情況下刪除觸發(fā)器张症。
注意:刪除一個(gè)表的同時(shí)仓技,也會(huì)自動(dòng)刪除該表上的觸發(fā)器。另外吠冤,觸發(fā)器不能更新或覆蓋浑彰,為了修改一個(gè)觸發(fā)器,必須先刪除它拯辙,再重新創(chuàng)建郭变。
刪除觸發(fā)器
使用 DROP TRIGGER 語(yǔ)句可以刪除 MySQL 中已經(jīng)定義的觸發(fā)器。
【實(shí)例】刪除 double_salary 觸發(fā)器涯保,輸入的 SQL 語(yǔ)句和執(zhí)行過程如下所示诉濒。
mysql> DROP TRIGGER double_salary;
Query OK, 0 rows affected (0.03 sec)
Event事件(定時(shí)任務(wù))是什么
在數(shù)據(jù)庫(kù)管理中,經(jīng)常要周期性的執(zhí)行某一命令或 SQL 語(yǔ)句夕春,于是 MySQL 5.1 版本以后就提供了事件未荒,它可以很方便的實(shí)現(xiàn) MySQL 數(shù)據(jù)庫(kù)的計(jì)劃任務(wù),定期運(yùn)行指定命令及志,使用起來非常簡(jiǎn)單方便片排。
事件(Event)也可稱為事件調(diào)度器(Event Scheduler),是用來執(zhí)行定時(shí)任務(wù)的一組 SQL 集合速侈,可以通俗理解成 MySQL 中的定時(shí)器率寡。一個(gè)事件可調(diào)用一次,也可周期性的啟動(dòng)倚搬。
事件可以作為定時(shí)任務(wù)調(diào)度器冶共,取代部分原來只能用操作系統(tǒng)的計(jì)劃任務(wù)才能執(zhí)行的工作。另外每界,更值得一提的是捅僵,MySQL 的事件可以實(shí)現(xiàn)每秒鐘執(zhí)行一個(gè)任務(wù),非常適合對(duì)實(shí)時(shí)性要求較高的環(huán)境眨层,而操作系統(tǒng)的計(jì)劃任務(wù)只能精確到每分鐘一次庙楚。
事件和觸發(fā)器類似,都是在某些事情發(fā)生時(shí)啟動(dòng)趴樱。當(dāng)數(shù)據(jù)庫(kù)啟動(dòng)一條語(yǔ)句的時(shí)候馒闷,觸發(fā)器就啟動(dòng)了,而事件是根據(jù)調(diào)度事件來啟動(dòng)的伊佃。由于他們彼此相似窜司,所以事件也稱為臨時(shí)性觸發(fā)器。
查看事件是否開啟
在 MySQL 中航揉,調(diào)度器 event_scheduler 負(fù)責(zé)調(diào)用事件塞祈。我們可以通過以下幾種命令查看事件是否開啟,一般情況下默認(rèn)值為 OFF帅涂。SQL 命令和運(yùn)行結(jié)果如下:
mysql> SHOW VARIABLES LIKE 'event_scheduler';
+-----------------+-------+
| Variable_name | Value |
+-----------------+-------+
| event_scheduler | OFF |
+-----------------+-------+
1 row in set, 1 warning (0.02 sec)
mysql> SELECT @@event_scheduler;
+-------------------+
| @@event_scheduler |
+-------------------+
| OFF |
+-------------------+
1 row in set (0.00 sec)
mysql> SHOW PROCESSLIST;
+----+------+-----------------+------+---------+------+----------+------------------+
| Id | User | Host | db | Command | Time | State | Info |
+----+------+-----------------+------+---------+------+----------+------------------+
| 2 | root | localhost:56279 | NULL | Query | 0 | starting | SHOW PROCESSLIST |
+----+------+-----------------+------+---------+------+----------+------------------+
1 row in set (0.01 sec)
從結(jié)果可以看出议薪,事件沒有開啟尤蛮。因?yàn)閰?shù) event_scheduler 的值為 OFF,并且在 PROCESSLIST 中查看不到 event_scheduler 的信息斯议。如果參數(shù) event_scheduler 的值為 ON产捞,或者在 PROCESSLIST 中顯示了 event_scheduler 的信息,則說明事件已經(jīng)開啟哼御。
開啟事件
開啟事件主要通過以下兩種方式實(shí)現(xiàn)坯临。
通過設(shè)置全局參數(shù)修改
可以使用 SET GLOBAL 命令設(shè)定全局變量 event_scheduler 的值,開啟或關(guān)閉事件恋昼。將 event_scheduler 參數(shù)的值設(shè)置為 ON看靠,表示開啟事件;設(shè)置為 OFF液肌,則關(guān)閉事件挟炬。
例如,要開啟事件可以在命令行窗口中輸入以下命令嗦哆。
mysql> SET GLOBAL event_scheduler = ON ;
Query OK, 0 rows affected (0.06 sec)
mysql> SHOW VARIABLES LIKE 'event_scheduler';
+-----------------+-------+
| Variable_name | Value |
+-----------------+-------+
| event_scheduler | ON |
+-----------------+-------+
1 row in set, 1 warning (0.01 sec)
結(jié)果顯示谤祖,event_scheduler 的值為 ON,表示事件已經(jīng)開啟老速。
通過 SET GLOBAL 命令開啟或關(guān)閉事件粥喜,MySQL 重啟服務(wù)后事件又會(huì)回到原來的狀態(tài),如果想要始終開啟或關(guān)閉事件烁峭,可以修改 MySQL 配置文件容客。
更改配置文件
在 MySQL 配置文件中找到 [mysqld] 選項(xiàng)秕铛,然后在下面添加以下代碼開啟事件约郁。
event_scheduler = ON
在配置文件中添加代碼并保存文件后,重啟 MySQL 服務(wù)才能生效但两。
通過該方法開啟或關(guān)閉事件鬓梅,重啟 MySQL 服務(wù)后,不會(huì)回到原來的狀態(tài)谨湘。例如绽快,此時(shí)重啟 MySQL 服務(wù)器,然后查看事件是否開啟紧阔。
mysql> SHOW VARIABLES LIKE 'event_scheduler';
+-----------------+-------+
| Variable_name | Value |
+-----------------+-------+
| event_scheduler | ON |
+-----------------+-------+
1 row in set, 1 warning (0.01 sec)
結(jié)果顯示坊罢,參數(shù) event_scheduler 的值為 ON,表示已經(jīng)開啟擅耽。
MySQL創(chuàng)建事件
在 MySQL 中活孩,可以通過 CREATE EVENT 語(yǔ)句來創(chuàng)建事件,其語(yǔ)法格式如下:
CREATE EVENT [IF NOT EXISTS] event_name
ON SCHEDULE schedule
[ON COMPLETION [NOT] PRESERVE]
[ENABLE | DISABLE | DISABLE ON SLAVE]
[COMMENT 'comment']
DO event_body;
從上面的語(yǔ)法可以看出乖仇,CRATE EVENT 語(yǔ)句由多個(gè)子句組成憾儒,各子句的詳細(xì)說明如下表所示询兴。
子句 | 說明 |
---|---|
DEFINER | 可選 用于定義事件執(zhí)行時(shí)檢查權(quán)限的用戶 |
IF NOT EXISTS | 可選 用于判斷要?jiǎng)?chuàng)建的事件是否存在 |
EVENT event_name | 必選 用于指定事件名稱,event_name 的最大長(zhǎng)度為 64 個(gè)字符 如果未指定 event_name起趾,則默認(rèn)為當(dāng)前的 MySQL 用戶名(不區(qū)分大小寫) |
ON SCHEDULE schedule | 必選 用于定義執(zhí)行的時(shí)間和時(shí)間間隔 schedule 表示觸發(fā)點(diǎn) |
ON COMPLETION [NOT] PRESERVE | 可選 用于定義事件是否循環(huán)執(zhí)行诗舰,即是一次執(zhí)行還是永久執(zhí)行,默認(rèn)為一次執(zhí)行训裆,即 NOT PRESERVE |
ENABLE | DISABLE | DISABLE ON SLAVE | 可選眶根,用于指定事件的一種屬性。 其中边琉,關(guān)鍵字 ENABLE 表示該事件是活動(dòng)的汛闸,即調(diào)度器檢查事件是否必須調(diào)用; 關(guān)鍵字 DISABLE 表示該事件是關(guān)閉的艺骂,即事件的聲明存儲(chǔ)到目錄中诸老,但是調(diào)度器不會(huì)檢查它是否應(yīng)該調(diào)用; 關(guān)鍵字 DISABLE ON SLAVE 表示事件在從機(jī)中是關(guān)閉的钳恕。 如果不指定以上 3 個(gè)選項(xiàng)中的任何一個(gè)别伏,默認(rèn)為 ENABLE |
COMMENT 'comment' | 可選,用于定義事件的注釋 |
DO event_body | 必選 用于指定事件啟動(dòng)時(shí)所要執(zhí)行的代碼忧额,可以是任何有效的 SQL 語(yǔ)句厘肮、存儲(chǔ)過程或者一個(gè)計(jì)劃執(zhí)行的事件。 如果包含多條語(yǔ)句睦番,則可以使用 BEGIN..END 復(fù)合結(jié)構(gòu) |
在 ON SCHEDULE 子句中类茂,參數(shù) schedule 的值為一個(gè) AT 子句,用于指定事件在某個(gè)時(shí)刻發(fā)生托嚣,其語(yǔ)法格式如下:
AT timestamp [+ INTERVAL interval]...
| EVERY interval
[STARTS timestamp [+ INTERVAL interval] ...]
[ENDS timestamp[+ INTERVAL interval]...]
參數(shù)說明如下:
- timestamp:一般用于只執(zhí)行一次巩检,表示一個(gè)具體的時(shí)間點(diǎn),后面加上一個(gè)時(shí)間間隔示启,表示在這個(gè)時(shí)間間隔后事件發(fā)生兢哭。
- EVERY 子句:用于事件在指定時(shí)間區(qū)間內(nèi)每隔多長(zhǎng)時(shí)間發(fā)生一次,其中 STARTS 子句用于指定開始時(shí)間夫嗓;ENDS 子句用于指定結(jié)束時(shí)間迟螺。
- interval:一般用于周期性執(zhí)行,表示一個(gè)從現(xiàn)在開始的時(shí)間舍咖,其值由一個(gè)數(shù)值和單位構(gòu)成矩父。例如,使用“4 WEEK”表示 4 周排霉,使用“'1:10'HOUR_MINUTE”表示 1 小時(shí) 10 分鐘窍株。間隔的長(zhǎng)短用 DATE_ADD() 函數(shù)支配。
interval 參數(shù)可以是以下值:
**YEAR** | QUARTER | **MONTH** | **DAY** | **HOUR** | **MINUTE** |
WEEK | **SECOND** | YEAR_MONTH | DAY_HOUR | DAY_MINUTE |
DAY_SECOND | HOUR_MINUTE | HOUR_SECOND | MINUTE_SECOND
一般情況下,不建議使用不標(biāo)準(zhǔn)(以上未加粗關(guān)鍵字)的時(shí)間單位夹姥。
例子:在 test 數(shù)據(jù)庫(kù)中創(chuàng)建一個(gè)名稱為 e_test 的事件杉武,用于每隔 5 秒向表 tb_eventtest 中插入一條數(shù)據(jù)。
創(chuàng)建 tb_eventtest 表辙售,SQL 語(yǔ)句和運(yùn)行結(jié)果如下:
mysql> CREATE TABLE tb_eventtest(
-> id INT(11) PRIMARY KEY AUTO_INCREMENT,
-> user VARCHAR(20),
-> createtime DATETIME);
Query OK, 0 rows affected (0.07 sec)
創(chuàng)建 e_test 事件轻抱,SQL 語(yǔ)句和運(yùn)行結(jié)果如下:
mysql> CREATE EVENT IF NOT EXISTS e_test ON SCHEDULE EVERY 5 SECOND
-> ON COMPLETION PRESERVE
-> DO INSERT INTO tb_eventtest(user,createtime)VALUES('MySQL',NOW());
Query OK, 0 rows affected (0.04 sec)
創(chuàng)建事件后,查詢 tb_eventtest 中的數(shù)據(jù)旦部,SQL 語(yǔ)句和運(yùn)行結(jié)果如下:
mysql> SELECT * FROM tb_eventtest;
+----+-------+---------------------+
| id | user | createtime |
+----+-------+---------------------+
| 1 | MySQL | 2020-05-21 10:41:39 |
| 2 | MySQL | 2020-05-21 10:41:44 |
| 3 | MySQL | 2020-05-21 10:41:49 |
| 4 | MySQL | 2020-05-21 10:41:54 |
+----+-------+---------------------+
4 rows in set (0.01 sec)
從結(jié)果可以看出祈搜,系統(tǒng)每隔 5 秒插入一條數(shù)據(jù),這說明事件創(chuàng)建執(zhí)行成功了士八。
MySQL查看事件
創(chuàng)建好事件后容燕,用戶可以通過以下 3 種方式來查看事件的狀態(tài)信息:
- 查看 mysql.event
- 查看 information_schema.events
- 切換到相應(yīng)的數(shù)據(jù)庫(kù)后執(zhí)行 SHOW EVENTS;
查看 information_schema.events 表中的事件狀態(tài)信息。SQL 語(yǔ)句和運(yùn)行結(jié)果如下:
mysql> SELECT * FROM information_schema.events limit 1\G
*************************** 1. row ***************************
EVENT_CATALOG: def
EVENT_SCHEMA: test
EVENT_NAME: e_test
DEFINER: root@localhost
TIME_ZONE: SYSTEM
EVENT_BODY: SQL
EVENT_DEFINITION: INSERT INTO tb_eventtest(user,createtime)VALUES('MySQL',NOW())
EVENT_TYPE: RECURRING
EXECUTE_AT: NULL
INTERVAL_VALUE: 5
INTERVAL_FIELD: SECOND
SQL_MODE: ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION
STARTS: 2020-05-21 10:41:39
ENDS: NULL
STATUS: ENABLED
ON_COMPLETION: PRESERVE
CREATED: 2020-05-21 10:41:39
LAST_ALTERED: 2020-05-21 10:41:39
LAST_EXECUTED: 2020-05-21 12:38:54
EVENT_COMMENT:
ORIGINATOR: 1
CHARACTER_SET_CLIENT: gbk
COLLATION_CONNECTION: gbk_chinese_ci
DATABASE_COLLATION: utf8_unicode_ci
1 row in set (0.08 sec)
以上參數(shù)說明如下表所示:
參數(shù)名 | 說明 |
---|---|
EVENT_CATALOG | 事件存放目錄婚度,一般情況下蘸秘,值為 def,不建議修改 |
EVENT_SCHEMA | 事件所在的數(shù)據(jù)庫(kù) |
EVENT_NAME | 事件名稱 |
DEFINER | 事件的定義者 |
TIME_ZONE | 事件使用的時(shí)區(qū)蝗茁,默認(rèn)是 SYSTEM醋虏,不建議修改 |
EVENT_BODY | 一般情況下,值為 SQL哮翘,不建議修改 |
EVENT_DEFINITION | 該事件的內(nèi)容颈嚼,可以是具體的 INSERT 等 SQL,也可以是一個(gè)調(diào)用的存儲(chǔ)過程 |
EVENT_TYPE | 事件類型饭寺,這個(gè)參數(shù)比較重要阻课,在定義時(shí)指定 有兩個(gè)值:RECURRING 和 ONE TIME RECURRING 表示只要符合條件就會(huì)重復(fù)執(zhí)行,RECURRING 類型的事件一般為 NULL艰匙,表示該事件的預(yù)計(jì)執(zhí)行時(shí)間 ONE TIME 只會(huì)調(diào)用 EXECUTE_AT限煞,針對(duì) one-time 類型的事件有效 |
INTERVAL_VALUE | 針對(duì) RECURRING 類型的事件有效,表示執(zhí)行間隔長(zhǎng)度 |
INTERVAL_FIELD | 針對(duì) RECURRING 類型的事件有效旬薯,表示執(zhí)行間隔的單位晰骑,一般是 SECOND适秩,DAY 等值绊序,可參考創(chuàng)建語(yǔ)法 |
SQL_MODE | 當(dāng)前事件采用的 SQL_MODE |
STARTS | 針對(duì) RECURRING 類型的事件有效,表示一個(gè)事件從哪個(gè)時(shí)間點(diǎn)開始執(zhí)行秽荞,和 one-time 的 EXECUTE_AT 功能類似骤公。 為 NULL 時(shí)表示一符合條件就開始執(zhí)行 |
ENDS | 針對(duì) RECURRING 類型的事件有效,表示一個(gè)事件到了哪個(gè)時(shí)間點(diǎn)后不再執(zhí)行扬跋,如果為 NULL 就是永不停止 |
STATUS | 一般有三個(gè)值阶捆,ENABLED、DISABLED 和 SLAVESIDE_DISABLED |
ON_COMPLETION | 只有兩個(gè)值,PRESERVE 和 NOT PRESERVE |
CREATED | 事件的創(chuàng)建時(shí)間 |
LAST_ALTERED | 事件最近一次被修改的時(shí)間 |
LAST_EXECUTED | 事件最近一次執(zhí)行的時(shí)間洒试,如果為 NULL 表示從未執(zhí)行過 |
EVENT_COMMENT | 事件的注釋信息 |
ORIGINATOR | 當(dāng)前事件創(chuàng)建時(shí)的 server-id倍奢,用于主從上的處理,比如 SLAVESIDE_DISABLED |
CHARACTER_SET_CLIENT | 事件創(chuàng)建時(shí)的客戶端字符集 |
COLLATION_CONNECTION | 事件創(chuàng)建時(shí)的連接字符校驗(yàn)規(guī)則 |
DATABASE_COLLATION | 事件創(chuàng)建時(shí)的數(shù)據(jù)庫(kù)字符集校驗(yàn)規(guī)則 |
MySQL修改和刪除事件
修改事件
在 MySQL 中垒棋,事件創(chuàng)建之后卒煞,可以使用 ALTER EVENT 語(yǔ)句修改其定義和相關(guān)屬性。
修改事件的語(yǔ)法格式如下:
ALTER EVENT event_name
ON SCHEDULE schedule
[ON COMPLETION [NOT] PRESERVE]
[ENABLE | DISABLE | DISABLE ON SLAVE]
[COMMENT 'comment']
DO event_body;
ALTER EVENT 語(yǔ)句還有一個(gè)用法就是讓一個(gè)事件關(guān)閉或再次讓其活動(dòng)叼架。
例子:修改 e_test 事件畔裕,讓其每隔 30 秒向表 tb_eventtest 中插入一條數(shù)據(jù),SQL 語(yǔ)句和運(yùn)行結(jié)果如下所示:
mysql> ALTER EVENT e_test ON SCHEDULE EVERY 30 SECOND
-> ON COMPLETION PRESERVE
-> DO INSERT INTO tb_eventtest(user,createtime) VALUES('MySQL',NOW());
Query OK, 0 rows affected (0.04 sec)
mysql> TRUNCATE TABLE tb_eventtest;
Query OK, 0 rows affected (0.04 sec)
mysql> SELECT * FROM tb_eventtest;
+----+-------+---------------------+
| id | user | createtime |
+----+-------+---------------------+
| 1 | MySQL | 2020-05-21 13:23:49 |
| 2 | MySQL | 2020-05-21 13:24:19 |
+----+-------+---------------------+
2 rows in set (0.00 sec)
由結(jié)果可以看出乖订,修改事件后扮饶,表 tb_eventtest 中的數(shù)據(jù)由原來的每 5 秒插入一條,變?yōu)槊?30 秒插入一條乍构。
使用 ALTER EVENT 語(yǔ)句還可以臨時(shí)關(guān)閉一個(gè)已經(jīng)創(chuàng)建的事件甜无。
例子:臨時(shí)關(guān)閉事件 e_test 的具體代碼如下所示:
mysql> ALTER EVENT e_test DISABLE;
Query OK, 0 rows affected (0.00 sec)
查詢 tb_eventtest 表中的數(shù)據(jù),SQL 語(yǔ)句如下:
SELECT * FROM tb_eventtest;
為了確定事件已關(guān)閉哥遮,可以查詢兩次(每次間隔 1 分鐘)tb_eventtest 表的數(shù)據(jù)毫蚓,SQL 語(yǔ)句和運(yùn)行結(jié)果如下所示:
mysql> TRUNCATE TABLE tb_eventtest;
Query OK, 0 rows affected (0.05 sec)
mysql> SELECT * FROM tb_eventtest;
Empty set (0.00 sec)
mysql> SELECT * FROM tb_eventtest;
Empty set (0.00 sec)
由結(jié)果可以看出,臨時(shí)關(guān)閉事件后昔善,系統(tǒng)就不再繼續(xù)向表 tb_eventtest 中插入數(shù)據(jù)了元潘。
刪除事件
在 MySQL 中,可以使用 DROP EVENT 語(yǔ)句刪除已經(jīng)創(chuàng)建的事件君仆。語(yǔ)法格式如下:
DROP EVENT [IF EXISTS] event_name;
例子:刪除事件 e_test翩概,SQL 語(yǔ)句和運(yùn)行結(jié)果如下:
mysql> DROP EVENT IF EXISTS e_test;
Query OK, 0 rows affected (0.01 sec)
mysql> SELECT * FROM information_schema.events \G
Empty set (0.00 sec)
存儲(chǔ)函數(shù)詳解
存儲(chǔ)函數(shù)和存儲(chǔ)過程一樣,都是在數(shù)據(jù)庫(kù)中定義一些 SQL 語(yǔ)句的集合返咱。存儲(chǔ)函數(shù)可以通過 return 語(yǔ)句返回函數(shù)值钥庇,主要用于計(jì)算并返回一個(gè)值。而存儲(chǔ)過程沒有直接返回值咖摹,主要用于執(zhí)行操作评姨。
在 MySQL 中,使用 CREATE FUNCTION 語(yǔ)句來創(chuàng)建存儲(chǔ)函數(shù)萤晴,其語(yǔ)法形式如下:
CREATE FUNCTION sp_name ([func_parameter[...]])
RETURNS type
[characteristic ...] routine_body
其中:
- sp_name 參數(shù):表示存儲(chǔ)函數(shù)的名稱吐句;
- func_parameter:表示存儲(chǔ)函數(shù)的參數(shù)列表;
- RETURNS type:指定返回值的類型店读;
- characteristic 參數(shù):指定存儲(chǔ)函數(shù)的特性嗦枢,該參數(shù)的取值與存儲(chǔ)過程是一樣的;
- routine_body 參數(shù):表示 SQL 代碼的內(nèi)容屯断,可以用 BEGIN...END 來標(biāo)示 SQL 代碼的開始和結(jié)束文虏。
注意:在具體創(chuàng)建函數(shù)時(shí)侣诺,函數(shù)名不能與已經(jīng)存在的函數(shù)名重名。除了上述要求外氧秘,推薦函數(shù)名命名(標(biāo)識(shí)符)為 function_xxx 或者 func_xxx年鸳。
func_parameter 可以由多個(gè)參數(shù)組成,其中每個(gè)參數(shù)由參數(shù)名稱和參數(shù)類型組成丸相,其形式如下:
[IN | OUT | INOUT] param_name type;
其中:
- IN 表示輸入?yún)?shù)阻星,OUT 表示輸出參數(shù),INOUT 表示既可以輸入也可以輸出已添;
- param_name 參數(shù)是存儲(chǔ)函數(shù)的參數(shù)名稱妥箕;
- type 參數(shù)指定存儲(chǔ)函數(shù)的參數(shù)類型,該類型可以是 MySQL 數(shù)據(jù)庫(kù)的任意數(shù)據(jù)類型更舞。
創(chuàng)建函數(shù)與創(chuàng)建存儲(chǔ)過程一樣畦幢,需要通過命令 DELIMITER //
將 SQL 語(yǔ)句的結(jié)束符由“;”修改為“//”,最后通過命令 DELIMITER ;
將結(jié)束符號(hào)修改成 SQL 語(yǔ)句中默認(rèn)的結(jié)束符號(hào)缆蝉。
如果在存儲(chǔ)函數(shù)中的 RETURN 語(yǔ)句返回一個(gè)類型不同于函數(shù)的 RETURNS 子句中指定類型的值宇葱,返回值將被強(qiáng)制為恰當(dāng)?shù)念愋汀1热缈罚绻粋€(gè)函數(shù)返回一個(gè) ENUM 或 SET 值黍瞧,但是 RETURN 語(yǔ)句返回一個(gè)整數(shù),對(duì)于 SET 成員集的相應(yīng)的 ENUM 成員原杂,從函數(shù)返回的值是字符串印颤。
由于存儲(chǔ)函數(shù)和存儲(chǔ)過程的查看、修改穿肄、刪除等操作幾乎相同年局,所以我們不再詳細(xì)講解如何操作存儲(chǔ)函數(shù)了。
查看存儲(chǔ)函數(shù)的語(yǔ)法如下:
SHOW FUNCTION STATUS LIKE 存儲(chǔ)函數(shù)名;
SHOW CREATE FUNCTION 存儲(chǔ)函數(shù)名;
SELECT * FROM information_schema.Routines WHERE ROUTINE_NAME=存儲(chǔ)函數(shù)名;
可以發(fā)現(xiàn)咸产,操作存儲(chǔ)函數(shù)和操作存儲(chǔ)過程不同的是將 PROCEDURE 替換成了 FUNCTION矢否。同樣,修改存儲(chǔ)函數(shù)的語(yǔ)法如下:
ALTER FUNCTION 存儲(chǔ)函數(shù)名 [ 特征 ... ]
存儲(chǔ)函數(shù)的特征與存儲(chǔ)過程的基本一樣。
刪除存儲(chǔ)過程的語(yǔ)法如下:
DROP FUNCTION [ IF EXISTS ] <函數(shù)名>
MySQL調(diào)用存儲(chǔ)過程和函數(shù)
存儲(chǔ)過程和存儲(chǔ)函數(shù)都是存儲(chǔ)在服務(wù)器端的 SQL 語(yǔ)句集合。要想使用這些已經(jīng)定義好的存儲(chǔ)過程和存儲(chǔ)函數(shù)就必須要通過調(diào)用的方式來實(shí)現(xiàn)趟佃。
存儲(chǔ)過程通過 CALL 語(yǔ)句來調(diào)用,存儲(chǔ)函數(shù)的使用方法與 MySQL 內(nèi)部函數(shù)的使用方法相同亿絮。執(zhí)行存儲(chǔ)過程和存儲(chǔ)函數(shù)需要擁有 EXECUTE 權(quán)限(EXECUTE 權(quán)限的信息存儲(chǔ)在 information_schema 數(shù)據(jù)庫(kù)下的 USER_PRIVILEGES 表中)。
調(diào)用存儲(chǔ)過程
MySQL 中使用 CALL 語(yǔ)句來調(diào)用存儲(chǔ)過程。調(diào)用存儲(chǔ)過程后,數(shù)據(jù)庫(kù)系統(tǒng)將執(zhí)行存儲(chǔ)過程中的 SQL 語(yǔ)句壶谒,然后將結(jié)果返回給輸出值。
CALL 語(yǔ)句接收存儲(chǔ)過程的名字以及需要傳遞給它的任意參數(shù)膳沽,基本語(yǔ)法形式如下:
CALL sp_name([parameter[...]]);
其中,sp_name 表示存儲(chǔ)過程的名稱,parameter 表示存儲(chǔ)過程的參數(shù)挑社。
因?yàn)榇鎯?chǔ)過程實(shí)際上也是一種函數(shù)陨界,所以存儲(chǔ)過程名后需要有( )
符號(hào),即使不傳遞參數(shù)也需要痛阻。
調(diào)用存儲(chǔ)函數(shù)
在 MySQL 中菌瘪,存儲(chǔ)函數(shù)的使用方法與 MySQL 內(nèi)部函數(shù)的使用方法是一樣的。換言之阱当,用戶自己定義的存儲(chǔ)函數(shù)與 MySQL 內(nèi)部函數(shù)是一個(gè)性質(zhì)的俏扩。區(qū)別在于,存儲(chǔ)函數(shù)是用戶自己定義的弊添,而內(nèi)部函數(shù)是 MySQL 開發(fā)者定義的录淡。
MySQL變量的定義和賦值
在 MySQL 中,除了支持標(biāo)準(zhǔn)的存儲(chǔ)過程和函數(shù)外油坝,還引入了表達(dá)式嫉戚。表達(dá)式與其它高級(jí)語(yǔ)言的表達(dá)式一樣,由變量澈圈、運(yùn)算符和流程控制來構(gòu)成彬檀。
變量是表達(dá)式語(yǔ)句中最基本的元素,可以用來臨時(shí)存儲(chǔ)數(shù)據(jù)瞬女。在存儲(chǔ)過程和函數(shù)中都可以定義和使用變量窍帝。用戶可以使用 DECLARE 關(guān)鍵字來定義變量,定義后可以為變量賦值诽偷。這些變量的作用范圍是 BEGIN...END 程序段中盯桦。
定義變量
MySQL 中可以使用 DECLARE 關(guān)鍵字來定義變量,其基本語(yǔ)法如下:
DECLARE var_name[,...] type [DEFAULT value]
其中:
- DECLARE 關(guān)鍵字是用來聲明變量的渤刃;
- var_name 參數(shù)是變量的名稱拥峦,這里可以同時(shí)定義多個(gè)變量;
- type 參數(shù)用來指定變量的類型卖子;
- DEFAULT value 子句將變量默認(rèn)值設(shè)置為 value略号,沒有使用 DEFAULT 子句時(shí),默認(rèn)值為 NULL洋闽。
為變量賦值
MySQL 中可以使用 SET 關(guān)鍵字來為變量賦值玄柠,SET 語(yǔ)句的基本語(yǔ)法如下:
SET var_name = expr[,var_name = expr]...
其中:
- SET 關(guān)鍵字用來為變量賦值;
- var_name 參數(shù)是變量的名稱诫舅;
- expr 參數(shù)是賦值表達(dá)式羽利。
注意:一個(gè) SET 語(yǔ)句可以同時(shí)為多個(gè)變量賦值,各個(gè)變量的賦值語(yǔ)句之間用逗號(hào)隔開刊懈。
MySQL 中還可以使用 SELECT..INTO 語(yǔ)句為變量賦值这弧。其基本語(yǔ)法如下:
SELECT col_name [...] INTO var_name[,...]
FROM table_name WEHRE condition
其中:
- col_name 參數(shù)表示查詢的字段名稱娃闲;
- var_name 參數(shù)是變量的名稱;
- table_name 參數(shù)指表的名稱匾浪;
- condition 參數(shù)指查詢條件皇帮。
注意:當(dāng)將查詢結(jié)果賦值給變量時(shí),該查詢語(yǔ)句的返回結(jié)果只能是單行蛋辈。
MySQL定義條件和處理程序
在程序的運(yùn)行過程中可能會(huì)遇到問題属拾,此時(shí)我們可以通過定義條件和處理程序來事先定義這些問題。
定義條件是指事先定義程序執(zhí)行過程中遇到的問題冷溶,處理程序定義了在遇到這些問題時(shí)應(yīng)當(dāng)采取的處理方式和解決辦法渐白,保證存儲(chǔ)過程和函數(shù)在遇到警告或錯(cuò)誤時(shí)能繼續(xù)執(zhí)行,從而增強(qiáng)程序處理問題的能力逞频,避免程序出現(xiàn)異常被停止執(zhí)行纯衍。
定義條件
MySQL 中可以使用 DECLARE 關(guān)鍵字來定義條件。其基本語(yǔ)法如下:
DECLARE condition_name CONDITION FOR condition_value
condition value:
SQLSTATE [VALUE] sqlstate_value | mysql_error_code
其中:
- condition_name 參數(shù)表示條件的名稱虏劲;
- condition_value 參數(shù)表示條件的類型托酸;
- sqlstate_value 參數(shù)和 mysql_error_code 參數(shù)都可以表示 MySQL 的錯(cuò)誤。sqlstate_value 表示長(zhǎng)度為 5 的字符串類型錯(cuò)誤代碼柒巫,mysql_error_code 表示數(shù)值類型錯(cuò)誤代碼励堡。例如 ERROR 1146(42S02) 中,sqlstate_value 值是 42S02堡掏,mysql_error_code 值是 1146应结。
定義處理程序
MySQL 中可以使用 DECLARE 關(guān)鍵字來定義處理程序。其基本語(yǔ)法如下:
DECLARE handler_type HANDLER FOR condition_value[...] sp_statement
handler_type:
CONTINUE | EXIT | UNDO
condition_value:
SQLSTATE [VALUE] sqlstate_value | condition_name | SQLWARNING | NOT FOUND | SQLEXCEPTION | mysql_error_code
其中泉唁,handler_type 參數(shù)指明錯(cuò)誤的處理方式鹅龄,該參數(shù)有 3 個(gè)取值。這 3 個(gè)取值分別是 CONTINUE亭畜、EXIT 和 UNDO扮休。
- CONTINUE 表示遇到錯(cuò)誤不進(jìn)行處理,繼續(xù)向下執(zhí)行拴鸵;
- EXIT 表示遇到錯(cuò)誤后馬上退出玷坠;
- UNDO 表示遇到錯(cuò)誤后撤回之前的操作,MySQL 中暫時(shí)還不支持這種處理方式劲藐。
注意:通常情況下八堡,執(zhí)行過程中遇到錯(cuò)誤應(yīng)該立刻停止執(zhí)行下面的語(yǔ)句,并且撤回前面的操作聘芜。但是兄渺,MySQL 中現(xiàn)在還不能支持 UNDO 操作。因此汰现,遇到錯(cuò)誤時(shí)最好執(zhí)行 EXIT 操作挂谍。如果事先能夠預(yù)測(cè)錯(cuò)誤類型叔壤,并且進(jìn)行相應(yīng)的處理,那么可以執(zhí)行 CONTINUE 操作凳兵。
參數(shù)指明錯(cuò)誤類型百新,該參數(shù)有 6 個(gè)取值:
- sqlstate_value:包含 5 個(gè)字符的字符串錯(cuò)誤值企软;
- condition_name:表示 DECLARE 定義的錯(cuò)誤條件名稱庐扫;
- SQLWARNING:匹配所有以 01 開頭的 sqlstate_value 值;
- NOT FOUND:匹配所有以 02 開頭的 sqlstate_value 值仗哨;
- SQLEXCEPTION:匹配所有沒有被 SQLWARNING 或 NOT FOUND 捕獲的 sqlstate_value 值形庭;
- mysql_error_code:匹配數(shù)值類型錯(cuò)誤代碼。
sp_statement 參數(shù)為程序語(yǔ)句段厌漂,表示在遇到定義的錯(cuò)誤時(shí)萨醒,需要執(zhí)行的一些存儲(chǔ)過程或函數(shù)。
例子:下面是定義處理程序的幾種方式苇倡,代碼如下:
//方法一:捕獲 sqlstate_value
DECLARE CONTINUE HANDLER FOR SQLSTATE '42S02' SET @info='CAN NOT FIND';
//方法二:捕獲 mysql_error_code
DECLARE CONTINUE HANDLER FOR 1146 SET @info='CAN NOT FIND';
//方法三:先定義條件富纸,然后調(diào)用
DECLARE can_not_find CONDITION FOR 1146;
DECLARE CONTINUE HANDLER FOR can_not_find SET @info='CAN NOT FIND';
//方法四:使用 SQLWARNING
DECLARE EXIT HANDLER FOR SQLWARNING SET @info='ERROR';
//方法五:使用 NOT FOUND
DECLARE EXIT HANDLER FOR NOT FOUND SET @info='CAN NOT FIND';
//方法六:使用 SQLEXCEPTION
DECLARE EXIT HANDLER FOR SQLEXCEPTION SET @info='ERROR';
上述代碼是 6 種定義處理程序的方法。
- 捕獲 sqlstate_value 值旨椒。如果遇到 sqlstate_value 值為 42S02晓褪,執(zhí)行 CONTINUE 操作,并且輸出“CAN NOT FIND”信息综慎。
- 捕獲 mysql_error_code 值涣仿。如果遇到 mysql_error_code 值為 1146, 執(zhí)行 CONTINUE 操作示惊,并且輸出“CAN NOT FIND”信息好港。
- 先定義條件,然后再調(diào)用條件米罚。這里先定義 can_not_find 條件钧汹,遇到 1146 錯(cuò)誤就執(zhí)行 CONTINUE 操作。
- 使用 SQLWARNING录择。SQLWARNING 捕獲所有以 01 開頭的 sqlstate_value 值拔莱,然后執(zhí)行 EXIT 操作,并且輸出“ERROR"信息糊肠。
- 使用 NOT FOUND辨宠。NOT FOUND 捕獲所有以 02 開頭的 sqlstate_value 值,然后執(zhí)行 EXIT 操作货裹,并且輸出“CAN NOT FIND”信息嗤形。
- 使用 SQLEXCEPTION。 SQLEXCEPTION 捕獲所有沒有被 SQLWARNING 或 NOT FOUND 捕獲的 sqlstate_value 值弧圆,然后執(zhí)行 EXIT 操作赋兵,并且輸出“ERROR”信息笔咽。
定義條件和處理順序,具體的執(zhí)行過程如下:
mysql> CREATE TABLE t8(s1 INT,PRIMARY KEY(s1));
Query OK, 0 rows affected (0.07 sec)
mysql> DELIMITER //
mysql> CREATE PROCEDURE handlerdemo()
-> BEGIN
-> DECLARE CONTINUE HANDLER FOR SQLSTATE '23000' SET @X2=1;
-> SET @X=1;
-> INSERT INTO t8 VALUES(1);
-> SET @X=2;
-> INSERT INTO t8 VALUES(1);
-> SET @X=3;
-> END //
Query OK, 0 rows affected (0.02 sec)
mysql> DELIMITER ;
mysql> CALL handlerdemo();
Query OK, 0 rows affected (0.01 sec)
mysql> SELECT @X;
+------+
| @X |
+------+
| 3 |
+------+
1 row in set (0.00 sec)
上述代碼中霹期,@X 是一個(gè)用戶變量叶组,執(zhí)行結(jié)果 @X 等于 3,這表明 MySQL 執(zhí)行到程序的末尾历造。
如果DECLARE CONTINUE HANDLER FOR SQLSTATE '23000' SET @X2=1;
這一行不存在甩十,第二個(gè) INSERT 因 PRIMARY KEY 約束而失敗之后,MySQL 可能已經(jīng)采取 EXIT 策略吭产,且 SELECT @X 可能已經(jīng)返回 2侣监。
注意:@X 表示用戶變量,使用 SET 語(yǔ)句為其賦值臣淤,用戶變量與連接有關(guān)橄霉,一個(gè)客戶端定義的變量不能被其他客戶端所使用,當(dāng)客戶端退出時(shí)邑蒋,該客戶端連接的所有變量將自動(dòng)釋放姓蜂。
MySQL游標(biāo)的定義及使用
在 MySQL 中,存儲(chǔ)過程或函數(shù)中的查詢有時(shí)會(huì)返回多條記錄医吊,而使用簡(jiǎn)單的 SELECT 語(yǔ)句钱慢,沒有辦法得到第一行、下一行或前十行的數(shù)據(jù)遮咖,這時(shí)可以使用游標(biāo)來逐條讀取查詢結(jié)果集中的記錄滩字。游標(biāo)在部分資料中也被稱為光標(biāo)。
關(guān)系數(shù)據(jù)庫(kù)管理系統(tǒng)實(shí)質(zhì)是面向集合的御吞,在 MySQL 中并沒有一種描述表中單一記錄的表達(dá)形式麦箍,除非使用 WHERE 子句來限制只有一條記錄被選中。所以有時(shí)我們必須借助于游標(biāo)來進(jìn)行單條記錄的數(shù)據(jù)處理陶珠。
一般通過游標(biāo)定位到結(jié)果集的某一行進(jìn)行數(shù)據(jù)修改挟裂。結(jié)果集是符合 SQL 語(yǔ)句的所有記錄的集合。
個(gè)人理解游標(biāo)就是一個(gè)標(biāo)識(shí)揍诽,用來標(biāo)識(shí)數(shù)據(jù)取到了什么地方诀蓉,可以把他理解成數(shù)組中的下標(biāo)。
不像多數(shù) DBMS暑脆,MySQL 游標(biāo)只能用于存儲(chǔ)過程和函數(shù)渠啤。
聲明游標(biāo)
MySQL 中使用 DECLARE 關(guān)鍵字來聲明游標(biāo),并定義相應(yīng)的 SELECT 語(yǔ)句添吗,根據(jù)需要添加 WHERE 和其它子句沥曹。其語(yǔ)法的基本形式如下:
DECLARE cursor_name CURSOR FOR select_statement;
其中,cursor_name 表示游標(biāo)的名稱;select_statement 表示 SELECT 語(yǔ)句妓美,可以返回一行或多行數(shù)據(jù)僵腺。
打開游標(biāo)
聲明游標(biāo)之后,要想從游標(biāo)中提取數(shù)據(jù)壶栋,必須首先打開游標(biāo)辰如。在 MySQL 中,打開游標(biāo)通過 OPEN 關(guān)鍵字來實(shí)現(xiàn)贵试,其語(yǔ)法格式如下:
OPEN cursor_name;
其中琉兜,cursor_name 表示所要打開游標(biāo)的名稱。需要注意的是锡移,打開一個(gè)游標(biāo)時(shí)呕童,游標(biāo)并不指向第一條記錄漆际,而是指向第一條記錄的前邊淆珊。
在程序中,一個(gè)游標(biāo)可以打開多次奸汇。用戶打開游標(biāo)后施符,其他用戶或程序可能正在更新數(shù)據(jù)表,所以有時(shí)會(huì)導(dǎo)致用戶每次打開游標(biāo)后擂找,顯示的結(jié)果都不同戳吝。
使用游標(biāo)
游標(biāo)順利打開后,可以使用 FETCH...INTO 語(yǔ)句來讀取數(shù)據(jù)贯涎,其語(yǔ)法形式如下:
FETCH cursor_name INTO var_name [,var_name]...
上述語(yǔ)句中听哭,將游標(biāo) cursor_name 中 SELECT 語(yǔ)句的執(zhí)行結(jié)果保存到變量參數(shù) var_name 中。變量參數(shù) var_name 必須在游標(biāo)使用之前定義塘雳。使用游標(biāo)類似高級(jí)語(yǔ)言中的數(shù)組遍歷陆盘,當(dāng)?shù)谝淮问褂糜螛?biāo)時(shí),此時(shí)游標(biāo)指向結(jié)果集的第一條記錄败明。
MySQL 的游標(biāo)是只讀的隘马,也就是說,你只能順序地從開始往后讀取結(jié)果集妻顶,不能從后往前酸员,也不能直接跳到中間的記錄。
關(guān)閉游標(biāo)
游標(biāo)使用完畢后讳嘱,要及時(shí)關(guān)閉幔嗦,在 MySQL 中,使用 CLOSE 關(guān)鍵字關(guān)閉游標(biāo)沥潭,其語(yǔ)法格式如下:
CLOSE cursor_name;
CLOSE 釋放游標(biāo)使用的所有內(nèi)部?jī)?nèi)存和資源邀泉,因此每個(gè)游標(biāo)不再需要時(shí)都應(yīng)該關(guān)閉。
在一個(gè)游標(biāo)關(guān)閉后叛氨,如果沒有重新打開呼渣,則不能使用它棘伴。但是,使用聲明過的游標(biāo)不需要再次聲明屁置,用 OPEN 語(yǔ)句打開它就可以了焊夸。
如果你不明確關(guān)閉游標(biāo),MySQL 將會(huì)在到達(dá) END 語(yǔ)句時(shí)自動(dòng)關(guān)閉它蓝角。游標(biāo)關(guān)閉之后阱穗,不能使用 FETCH 來使用該游標(biāo)。
MySQL流程控制語(yǔ)句詳解
在存儲(chǔ)過程和自定義函數(shù)中可以使用流程控制語(yǔ)句來控制程序的流程使鹅。MySQL 中流程控制語(yǔ)句有:IF 語(yǔ)句揪阶、CASE 語(yǔ)句、LOOP 語(yǔ)句患朱、LEAVE 語(yǔ)句鲁僚、ITERATE 語(yǔ)句、REPEAT 語(yǔ)句和 WHILE 語(yǔ)句等裁厅。
IF語(yǔ)句
IF 語(yǔ)句用來進(jìn)行條件判斷冰沙,根據(jù)是否滿足條件(可包含多個(gè)條件),來執(zhí)行不同的語(yǔ)句执虹,是流程控制中最常用的判斷語(yǔ)句拓挥。其語(yǔ)法的基本形式如下:
IF search_condition THEN statement_list
[ELSEIF search_condition THEN statement_list]...
[ELSE statement_list]
END IF
其中,search_condition 參數(shù)表示條件判斷語(yǔ)句袋励,如果返回值為 TRUE 侥啤,相應(yīng)的 SQL 語(yǔ)句列表(statement_list)被執(zhí)行;如果返回值為 FALSE茬故,則 ELSE 子句的語(yǔ)句列表被執(zhí)行盖灸。statement_list 可以包括一個(gè)或多個(gè)語(yǔ)句。
注意:MySQL 中的 IF( ) 函數(shù)不同于這里的 IF 語(yǔ)句均牢。
CASE語(yǔ)句
CASE 語(yǔ)句也是用來進(jìn)行條件判斷的糠雨,它提供了多個(gè)條件進(jìn)行選擇,可以實(shí)現(xiàn)比 IF 語(yǔ)句更復(fù)雜的條件判斷徘跪。CASE 語(yǔ)句的基本形式如下:
CASE case_value
WHEN when_value THEN statement_list
[WHEN when_value THEN statement_list]...
[ELSE statement_list]
END CASE
其中:
- case_value 參數(shù)表示條件判斷的變量甘邀,決定了哪一個(gè) WHEN 子句會(huì)被執(zhí)行;
- when_value 參數(shù)表示變量的取值垮庐,如果某個(gè) when_value 表達(dá)式與 case_value 變量的值相同松邪,則執(zhí)行對(duì)應(yīng)的 THEN 關(guān)鍵字后的 statement_list 中的語(yǔ)句;
- statement_list 參數(shù)表示 when_value 值沒有與 case_value 相同值時(shí)的執(zhí)行語(yǔ)句哨查。
- CASE 語(yǔ)句都要使用 END CASE 結(jié)束逗抑。
CASE 語(yǔ)句還有另一種形式。該形式的語(yǔ)法如下:
CASE
WHEN search_condition THEN statement_list
[WHEN search_condition THEN statement_list] ...
[ELSE statement_list]
END CASE
其中,search_condition 參數(shù)表示條件判斷語(yǔ)句邮府;statement_list 參數(shù)表示不同條件的執(zhí)行語(yǔ)句荧关。
與上述語(yǔ)句不同的是,該語(yǔ)句中的 WHEN 語(yǔ)句將被逐個(gè)執(zhí)行褂傀,直到某個(gè) search_condition 表達(dá)式為真忍啤,則執(zhí)行對(duì)應(yīng) THEN 關(guān)鍵字后面的 statement_list 語(yǔ)句。如果沒有條件匹配仙辟,ELSE 子句里的語(yǔ)句被執(zhí)行同波。
這里介紹的 CASE 語(yǔ)句與“控制流程函數(shù)”里描述的 SQL CASE 表達(dá)式的 CASE 語(yǔ)句有輕微的不同。這里的 CASE 語(yǔ)句不能有 ELSE NULL 語(yǔ)句叠国,并且用 END CASE 替代 END 來終止未檩。
LOOP 語(yǔ)句
LOOP 語(yǔ)句可以使某些特定的語(yǔ)句重復(fù)執(zhí)行。與 IF 和 CASE 語(yǔ)句相比粟焊,LOOP 只實(shí)現(xiàn)了一個(gè)簡(jiǎn)單的循環(huán)冤狡,并不進(jìn)行條件判斷。
LOOP 語(yǔ)句本身沒有停止循環(huán)的語(yǔ)句吆玖,必須使用 LEAVE 語(yǔ)句等才能停止循環(huán)筒溃,跳出循環(huán)過程。LOOP 語(yǔ)句的基本形式如下:
[begin_label:]LOOP
statement_list
END LOOP [end_label]
其中沾乘,begin_label 參數(shù)和 end_label 參數(shù)分別表示循環(huán)開始和結(jié)束的標(biāo)志,這兩個(gè)標(biāo)志必須相同浑测,而且都可以省略翅阵;statement_list 參數(shù)表示需要循環(huán)執(zhí)行的語(yǔ)句。
LEAVE 語(yǔ)句
LEAVE 語(yǔ)句主要用于跳出循環(huán)控制迁央。其語(yǔ)法形式如下:
LEAVE label
其中掷匠,label 參數(shù)表示循環(huán)的標(biāo)志,LEAVE 語(yǔ)句必須跟在循環(huán)標(biāo)志前面岖圈。
ITERATE 語(yǔ)句
ITERATE 是“再次循環(huán)”的意思讹语,用來跳出本次循環(huán),直接進(jìn)入下一次循環(huán)蜂科。ITERATE 語(yǔ)句的基本語(yǔ)法形式如下:
ITERATE label
其中顽决,label 參數(shù)表示循環(huán)的標(biāo)志,ITERATE 語(yǔ)句必須跟在循環(huán)標(biāo)志前面导匣。
說明:LEAVE 語(yǔ)句和 ITERATE 語(yǔ)句都用來跳出循環(huán)語(yǔ)句才菠,但兩者的功能是不一樣的。LEAVE 語(yǔ)句是跳出整個(gè)循環(huán)贡定,然后執(zhí)行循環(huán)后面的程序赋访。而 ITERATE 語(yǔ)句是跳出本次循環(huán),然后進(jìn)入下一次循環(huán)。使用這兩個(gè)語(yǔ)句時(shí)一定要區(qū)分清楚蚓耽。
REPEAT 語(yǔ)句
REPEAT 語(yǔ)句是有條件控制的循環(huán)語(yǔ)句渠牲,每次語(yǔ)句執(zhí)行完畢后,會(huì)對(duì)條件表達(dá)式進(jìn)行判斷步悠,如果表達(dá)式返回值為 TRUE嘱兼,則循環(huán)結(jié)束,否則重復(fù)執(zhí)行循環(huán)中的語(yǔ)句贤徒。
REPEAT 語(yǔ)句的基本語(yǔ)法形式如下:
[begin_label:] REPEAT
statement_list
UNTIL search_condition
END REPEAT [end_label]
其中:
- begin_label 為 REPEAT 語(yǔ)句的標(biāo)注名稱芹壕,該參數(shù)可以省略;
- REPEAT 語(yǔ)句內(nèi)的語(yǔ)句被重復(fù)接奈,直至 search_condition 返回值為 TRUE踢涌。
- statement_list 參數(shù)表示循環(huán)的執(zhí)行語(yǔ)句;
- search_condition 參數(shù)表示結(jié)束循環(huán)的條件序宦,滿足該條件時(shí)循環(huán)結(jié)束睁壁。
- REPEAT 循環(huán)都用 END REPEAT 結(jié)束。
WHILE 語(yǔ)句
WHILE 語(yǔ)句也是有條件控制的循環(huán)語(yǔ)句互捌。WHILE 語(yǔ)句和 REPEAT 語(yǔ)句不同的是潘明,WHILE 語(yǔ)句是當(dāng)滿足條件時(shí),執(zhí)行循環(huán)內(nèi)的語(yǔ)句秕噪,否則退出循環(huán)钳降。WHILE 語(yǔ)句的基本語(yǔ)法形式如下:
[begin_label:] WHILE search_condition DO
statement list
END WHILE [end label]
其中,search_condition 參數(shù)表示循環(huán)執(zhí)行的條件腌巾,滿足該條件時(shí)循環(huán)執(zhí)行遂填;statement_list 參數(shù)表示循環(huán)的執(zhí)行語(yǔ)句。WHILE 循環(huán)需要使用 END WHILE 來結(jié)束澈蝙。