作為一名優(yōu)秀的程序員,必須具備一些更高級的技能,下面我們就來探討一下程序員再 MySQL 都需要哪些高級的技能。
一、MySQL 存儲引擎
1、存儲引擎概述
數(shù)據(jù)庫最核心的一點就是用來存儲數(shù)據(jù),數(shù)據(jù)存儲就避免不了和磁盤打交道。那么數(shù)據(jù)以哪種方式進行存儲,如何存儲是存儲的關(guān)鍵所在。所以存儲引擎就相當(dāng)于是數(shù)據(jù)存儲的發(fā)動機,來驅(qū)動數(shù)據(jù)在磁盤層面進行存儲。
MySQL 的架構(gòu)可以按照三層模式來理解:
存儲引擎也是 MySQL 的組建,它是一種軟件,它所能做的和支持的功能主要有:
并發(fā)
支持事務(wù)
完整性約束
物理存儲
支持索引
性能幫助
MySQL 默認(rèn)支持多種存儲引擎,來適用不同數(shù)據(jù)庫應(yīng)用,用戶可以根據(jù)需要選擇合適的存儲引擎,下面是 MySQL 支持的存儲引擎
MyISAM
InnoDB
BDB
MEMORY
MERGE
EXAMPLE
NDB Cluster
ARCHIVE
CSV
BLACKHOLE
FEDERATED
默認(rèn)情況下,如果創(chuàng)建表不指定存儲引擎,會使用默認(rèn)的存儲引擎,如果要修改默認(rèn)的存儲引擎,那么就可以在參數(shù)文件中設(shè)置** default-table-type**,能夠查看當(dāng)前的存儲引擎
show variables like 'table_type';
奇怪,為什么沒有了呢?網(wǎng)上求證一下,在 5.5.3 取消了這個參數(shù)
可以通過下面兩種方法查詢當(dāng)前數(shù)據(jù)庫支持的存儲引擎
show engines \g
在創(chuàng)建新表的時候,可以通過增加 **ENGINE **關(guān)鍵字設(shè)置新建表的存儲引擎。
create table cxuan002(id int(10),name varchar(20)) engine = MyISAM;
上圖我們指定了 **MyISAM **的存儲引擎。
如果你不知道表的存儲引擎怎么辦?你可以通過 **show create table **來查看
如果不指定存儲引擎的話,從MySQL 5.1 版本之后,MySQL 的默認(rèn)內(nèi)置存儲引擎已經(jīng)是** InnoDB**了。建一張表看一下
如上圖所示,我們沒有指定默認(rèn)的存儲引擎,下面查看一下表
可以看到,默認(rèn)的存儲引擎是 InnoDB。
如果你的存儲引擎想要更換,可以使用
alter table cxuan003 engine = myisam;
來更換,更換完成后回顯示** 「0 rows affected」** ,但其實已經(jīng)操作成功
我們使用 **show create table **查看一下表的 sql 就知道
2、存儲引擎特性
下面會介紹幾個常用的存儲引擎以及它的基本特性,這些存儲引擎是 **MyISAM、InnoDB、MEMORY 和 MERGE **
(1)MyISAM
在 5.1 版本之前,MyISAM 是 MySQL 的默認(rèn)存儲引擎,MyISAM 并發(fā)性比較差,使用的場景比較少,主要特點是
不支持事務(wù)操作,ACID 的特性也就不存在了,這一設(shè)計是為了性能和效率考慮的。
不支持外鍵操作,如果強行增加外鍵,MySQL 不會報錯,只不過外鍵不起作用。
MyISAM 默認(rèn)的鎖粒度是表級鎖,所以并發(fā)性能比較差,加鎖比較快,鎖沖突比較少,不太容易發(fā)生死鎖的情況。
MyISAM 會在磁盤上存儲三個文件,文件名和表名相同,擴展名分別是** .frm(存儲表定義)、.MYD(MYData,存儲數(shù)據(jù))、MYI(MyIndex,存儲索引)。這里需要特別注意的是 MyISAM 只緩存索引文件,**并不緩存數(shù)據(jù)文件。
MyISAM 支持的索引類型有 全局索引(Full-Text)、B-Tree 索引、R-Tree 索引
Full-Text 索引:它的出現(xiàn)是為了解決針對文本的模糊查詢效率較低的問題。
B-Tree 索引:所有的索引節(jié)點都按照平衡樹的數(shù)據(jù)結(jié)構(gòu)來存儲,所有的索引數(shù)據(jù)節(jié)點都在葉節(jié)點
R-Tree索引:它的存儲方式和 B-Tree 索引有一些區(qū)別,主要設(shè)計用于存儲空間和多維數(shù)據(jù)的字段做索引,目前的 MySQL 版本僅支持 geometry 類型的字段作索引,相對于 BTREE,RTREE 的優(yōu)勢在于范圍查找。
數(shù)據(jù)庫所在主機如果宕機,MyISAM 的數(shù)據(jù)文件容易損壞,而且難以恢復(fù)。
增刪改查性能方面:SELECT 性能較高,適用于查詢較多的情況
(2)InnoDB
自從 MySQL 5.1 之后,默認(rèn)的存儲引擎變成了 InnoDB 存儲引擎,相對于 MyISAM,InnoDB 存儲引擎有了較大的改變,它的主要特點是
支持事務(wù)操作,具有事務(wù) ACID 隔離特性,默認(rèn)的隔離級別是可重復(fù)讀(repetable-read)、通過MVCC(并發(fā)版本控制)來實現(xiàn)的。能夠解決臟讀和不可重復(fù)讀的問題。
InnoDB 支持外鍵操作。
InnoDB 默認(rèn)的鎖粒度行級鎖,并發(fā)性能比較好,會發(fā)生死鎖的情況。
和 MyISAM 一樣的是,InnoDB 存儲引擎也有** .frm文件存儲表結(jié)構(gòu)** 定義,但是不同的是,InnoDB 的表數(shù)據(jù)與索引數(shù)據(jù)是存儲在一起的,都位于 B+ 數(shù)的葉子節(jié)點上,而 MyISAM 的表數(shù)據(jù)和索引數(shù)據(jù)是分開的。
InnoDB 有安全的日志文件,這個日志文件用于恢復(fù)因數(shù)據(jù)庫崩潰或其他情況導(dǎo)致的數(shù)據(jù)丟失問題,保證數(shù)據(jù)的一致性。
InnoDB 和 MyISAM 支持的索引類型相同,但具體實現(xiàn)因為文件結(jié)構(gòu)的不同有很大差異。
增刪改查性能方面,果執(zhí)行大量的增刪改操作,推薦使用 InnoDB 存儲引擎,它在刪除操作時是對行刪除,不會重建表。
(3)MEMORY
MEMORY 存儲引擎使用存在內(nèi)存中的內(nèi)容來創(chuàng)建表。每個 MEMORY 表實際只對應(yīng)一個磁盤文件,格式是** .frm。**MEMORY 類型的表訪問速度很快,因為其數(shù)據(jù)是存放在內(nèi)存中。默認(rèn)使用 HASH 索引。
(4)MERGE
MERGE 存儲引擎是一組 MyISAM 表的組合,MERGE 表本身沒有數(shù)據(jù),對 MERGE 類型的表進行查詢、更新、刪除的操作,實際上是對內(nèi)部的 MyISAM 表進行的。MERGE 表在磁盤上保留兩個文件,一個是** .frm **文件存儲表定義、一個是 **.MRG **文件存儲 MERGE 表的組成等。
3、選擇合適的存儲引擎
在實際開發(fā)過程中,我們往往會根據(jù)應(yīng)用特點選擇合適的存儲引擎。
MyISAM:如果應(yīng)用程序通常以檢索為主,只有少量的插入、更新和刪除操作,并且對事物的完整性、并發(fā)程度不是很高的話,通常建議選擇 MyISAM 存儲引擎。
InnoDB:如果使用到外鍵、需要并發(fā)程度較高,數(shù)據(jù)一致性要求較高,那么通常選擇 InnoDB 引擎,一般互聯(lián)網(wǎng)大廠對并發(fā)和數(shù)據(jù)完整性要求較高,所以一般都使用 InnoDB 存儲引擎。
MEMORY:MEMORY 存儲引擎將所有數(shù)據(jù)保存在內(nèi)存中,在需要快速定位下能夠提供及其迅速的訪問。MEMORY 通常用于更新不太頻繁的小表,用于快速訪問取得結(jié)果。
MERGE:MERGE 的內(nèi)部是使用 MyISAM 表,MERGE 表的優(yōu)點在于可以突破對單個 MyISAM 表大小的限制,并且通過將不同的表分布在多個磁盤上, 可以有效地改善 MERGE 表的訪問效率。
二、選擇合適的數(shù)據(jù)類型
我們會經(jīng)常遇見的一個問題就是,在建表時如何選擇合適的數(shù)據(jù)類型,通常選擇合適的數(shù)據(jù)類型能夠提高性能、減少不必要的麻煩,下面我們就來一起探討一下,如何選擇合適的數(shù)據(jù)類型。
1、CHAR 和 VARCHAR 的選擇
char 和 varchar 是我們經(jīng)常要用到的兩個存儲字符串的數(shù)據(jù)類型,char 一般存儲定長的字符串,它屬于固定長度的字符類型,比如下面
可以看到,不管你的值寫的是什么,一旦指定了 char 字符的長度,如果你的字符串長度不夠指定字符的長度的話,那么就用空格來填補,如果超過字符串長度的話,只存儲指定字符長度的字符。
這里注意一點:如果 MySQL 使用了非 嚴(yán)格模式的話,上面表格最后一行是可以存儲的。如果 MySQL 使用了 嚴(yán)格模式 的話,那么表格上面最后一行存儲會報錯。
如果使用了 varchar 字符類型,我們來看一下例子
可以看到,如果使用 varchar 的話,那么存儲的字節(jié)將根據(jù)實際的值進行存儲。你可能會疑惑為什么 varchar 的長度是 5 ,但是卻需要存儲 3 個字節(jié)或者 6 個字節(jié),這是因為使用 varchar 數(shù)據(jù)類型進行存儲時,默認(rèn)會在最后增加一個字符串長度,占用1個字節(jié)(如果列聲明的長度超過255,則使用兩個字節(jié))。varchar 不會填充空余的字符串。
一般使用 char 來存儲定長的字符串,比如「身份證號、手機號、郵箱等」;使用 varchar 來存儲不定長的字符串。由于 char 長度是固定的,所以它的處理速度要比 VARCHAR 快很多,但是缺點是浪費存儲空間,但是隨著 MySQL 版本的不斷演進,varchar 數(shù)據(jù)類型的性能也在不斷改進和提高,所以在許多應(yīng)用中,VARCHAR 類型更多的被使用。
在 MySQL 中,不同的存儲引擎對 CHAR 和 VARCHAR 的使用原則也有不同:
MyISAM:建議使用固定長度的數(shù)據(jù)列替代可變長度的數(shù)據(jù)列,也就是 CHAR;
MEMORY:使用固定長度進行處理、CHAR 和 VARCHAR 都會被當(dāng)作 CHAR 處理;
InnoDB:建議使用 VARCHAR 類型。
2、TEXT 與 BLOB
一般在保存較少的文本的時候,我們會選擇 CHAR 和 VARCHAR,在保存大數(shù)據(jù)量的文本時,我們往往選擇 TEXT 和 BLOB;TEXT 和 BLOB 的主要差別是 BLOB 能夠保存二進制數(shù)據(jù);而 TEXT 只能保存字符數(shù)據(jù),TEXT 往下細(xì)分有
TEXT
MEDIUMTEXT
LONGTEXT
BLOB 往下細(xì)分有
BLOB
MEDIUMBLOB
LONGBLOB
三種,它們最主要的區(qū)別就是存儲文本長度不同和存儲字節(jié)不同,用戶應(yīng)該根據(jù)實際情況選擇滿足需求的最小存儲類型,下面主要對 BLOB 和 TEXT 存在一些問題進行介紹
TEXT 和 BLOB 在刪除數(shù)據(jù)后會存在一些性能上的問題,為了提高性能,建議使用** OPTIMIZE TABLE** 功能對表進行碎片整理。
也可以使用合成索引來提高文本字段(BLOB 和 TEXT)的查詢性能。合成索引就是根據(jù)大文本(BLOB 和 TEXT)字段的內(nèi)容建立一個散列值,把這個值存在對應(yīng)列中,這樣就能夠根據(jù)散列值查找到對應(yīng)的數(shù)據(jù)行。一般使用散列算法比如 md5() 和 SHA1() ,如果散列算法生成的字符串帶有尾部空格,就不要把它們存在 CHAR 和 VARCHAR 中,下面我們就來看一下這種使用方式
首先創(chuàng)建一張表,表中記錄 blob 字段和 hash 值
向 cxuan005 中插入數(shù)據(jù),其中 hash 值作為 info 的散列值。
然后再插入兩條數(shù)據(jù)
插入一條 info 為 cxuan005 的數(shù)據(jù)
如果想要查詢 info 為 cxuan005 的數(shù)據(jù),可以通過查詢 hash 列來進行查詢
這是合成索引的例子,如果要對 BLOB 進行模糊查詢的話,就要使用前綴索引。
其他優(yōu)化 BLOB 和 TEXT 的方式:
非必要的時候不要檢索 BLOB 和 TEXT 索引
把 BLOB 或 TEXT 列分離到單獨的表中
3、浮點數(shù)和定點數(shù)的選擇
浮點數(shù)指的就是含有小數(shù)的值,浮點數(shù)插入到指定列中超過指定精度后,浮點數(shù)會四舍五入,MySQL 中的浮點數(shù)指的就是** float** 和 double,定點數(shù)指的是 decimal,定點數(shù)能夠更加精確的保存和顯示數(shù)據(jù)。下面通過一個示例講解一下浮點數(shù)精確性問題
首先創(chuàng)建一個表 cxuan006 ,只為了測試浮點數(shù)問題,所以這里我們選擇的數(shù)據(jù)類型是 float
然后分別插入兩條數(shù)據(jù)
然后執(zhí)行查詢,可以看到查詢出來的兩條數(shù)據(jù)執(zhí)行的舍入不同
為了清晰的看清楚浮點數(shù)與定點數(shù)的精度問題,再來看一個例子
先修改 cxuan006 的兩個字段為相同的長度和小數(shù)位數(shù)
然后插入兩條數(shù)據(jù)
執(zhí)行查詢操作,可以發(fā)現(xiàn),浮點數(shù)相較于定點數(shù)來說,會產(chǎn)生誤差
4、日期類型選擇
在 MySQL 中,用來表示日期類型的有 「DATE、TIME、DATETIME、TIMESTAMP」,在
這篇文中介紹過了日期類型的區(qū)別,我們這里就不再闡述了。下面主要介紹一下選擇
TIMESTAMP 和時區(qū)相關(guān),更能反映當(dāng)前時間,如果記錄的日期需要讓不同時區(qū)的人使用,最好使用 TIMESTAMP。
DATE 用于表示年月日,如果實際應(yīng)用值需要保存年月日的話就可以使用 DATE。
TIME 用于表示時分秒,如果實際應(yīng)用值需要保存時分秒的話就可以使用 TIME。
YEAR 用于表示年份,YEAR 有 2 位(最好使用4位)和 4 位格式的年。默認(rèn)是4位。如果實際應(yīng)用只保存年份,那么用 1 bytes 保存 YEAR 類型完全可以。不但能夠節(jié)約存儲空間,還能提高表的操作效率。
三、MySQL 字符集
下面來認(rèn)識一下 MySQL 字符集,簡單來說字符集就是一套文字符號和編碼、比較規(guī)則的集合。1960 年美國標(biāo)準(zhǔn)化組織 ANSI 發(fā)布了第一個計算機字符集,就是著名的 ASCII(American Standard Code for Information Interchange) 。自從 ASCII 編碼后,每個國家、國際組織都研究了一套自己的字符集,比如 ISO-8859-1、GBK 等。
但是每個國家都使用自己的字符集為移植性帶來了很大的困難。所以,為了統(tǒng)一字符編碼,**國際標(biāo)準(zhǔn)化組織(ISO) **指定了統(tǒng)一的字符標(biāo)準(zhǔn) - Unicode 編碼,它容納了幾乎所有的字符編碼。下面是一些常見的字符編碼
對數(shù)據(jù)庫來說,字符集是很重要的,因為數(shù)據(jù)庫存儲的數(shù)據(jù)大多數(shù)都是各種文字,字符集對數(shù)據(jù)庫的存儲、性能、系統(tǒng)的移植來說都非常重要。
MySQL 支持多種字符集,可以使用** show character set; **來查看所有可用的字符集
或者使用
select character_set_name, default_collate_name, description, maxlen from information_schema.character_sets;
來查看。
使用** information_schema.character_set **來查看字符集和校對規(guī)則。
四、索引的設(shè)計和使用
我們上面介紹到了索引的幾種類型并對不同的索引類型做了闡述,闡明了優(yōu)缺點等等,下面我們從設(shè)計角度來聊一下索引,關(guān)于索引,你必須要知道的一點就是:「索引是數(shù)據(jù)庫用來提高性能的最常用工具」。
1、索引概述
所有的 MySQL 類型都可以進行索引,對相關(guān)列使用索引是提高 SELECT 查詢性能的最佳途徑。MyISAM 和 InnoDB 都是使用 BTREE 作為索引,MySQL 5 不支持函數(shù)索引,但是支持** 前綴索引。**
前綴索引顧名思義就是對列字段的前綴做索引,前綴索引的長度和存儲引擎有關(guān)系。MyISAM 前綴索引的長度支持到 1000 字節(jié),InnoDB 前綴索引的長度支持到 767 字節(jié),索引值重復(fù)性越低,查詢效率也就越高。
在 MySQL 中,主要有下面這幾種索引
全局索引(FULLTEXT):全局索引,目前只有 MyISAM 引擎支持全局索引,它的出現(xiàn)是為了解決針對文本的模糊查詢效率較低的問題,并且只限于 CHAR、VARCHAR 和 TEXT 列。
哈希索引(HASH):哈希索引是 MySQL 中用到的唯一 key-value 鍵值對的數(shù)據(jù)結(jié)構(gòu),很適合作為索引。HASH 索引具有一次定位的好處,不需要像樹那樣逐個節(jié)點查找,但是這種查找適合應(yīng)用于查找單個鍵的情況,對于范圍查找,HASH 索引的性能就會很低。默認(rèn)情況下,MEMORY 存儲引擎使用 HASH 索引,但也支持 BTREE 索引。
B-Tree 索引:B 就是 Balance 的意思,BTree 是一種平衡樹,它有很多變種,最常見的就是 B+ Tree,它被 MySQL 廣泛使用。
R-Tree 索引:R-Tree 在 MySQL 很少使用,僅支持 geometry 數(shù)據(jù)類型,支持該類型的存儲引擎只有MyISAM、BDb、InnoDb、NDb、Archive幾種,相對于 B-Tree 來說,R-Tree 的優(yōu)勢在于范圍查找。
索引可以在創(chuàng)建表的時候進行創(chuàng)建,也可以單獨創(chuàng)建,下面我們采用單獨創(chuàng)建的方式,我們在 cxuan004 上創(chuàng)建前綴索引
我們使用 explain 進行分析,可以看到 cxuan004 使用索引的情況
如果不想使用索引,可以刪除索引,索引的刪除語法是
2、索引設(shè)計原則
創(chuàng)建索引的時候,要盡量考慮以下原則,便于提升索引的使用效率:
選擇索引位置,選擇索引最合適的位置是出現(xiàn)在 where 語句中的列,而不是** select **關(guān)鍵字后的選擇列表中的列。
選擇使用唯一索引,顧名思義,唯一索引的值是唯一的,可以更快速的確定某條記錄,例如學(xué)生的學(xué)號就適合使用唯一性索引,而學(xué)生的性別則不適合使用,因為不管搜索哪個值,都差不多有一半的行。
為經(jīng)常使用的字段建立索引,如果某個字段經(jīng)常用作查詢條件,那么這個字段的查詢速度在極大程度上影響整個表的查詢速度,因此為這樣的字段建立索引,可以提高整個表的查詢速度。
不要過度索引,限制索引數(shù)目,索引的數(shù)目不是越多越好,每個索引都會占據(jù)磁盤空間,索引越多,需要的磁盤空間就越大。
盡量使用前綴索引,如果索引的值很長,那么查詢速度會受到影響,這個時候應(yīng)該使用前綴索引,對列的某幾個字符進行索引,可以提高檢索效率。
利用最左前綴,在創(chuàng)建一個 n 列的索引時,實際上是創(chuàng)建了 MySQL 可利用的 n 個索引。多列索引可以起到幾個索引的作用,利用索引最左邊的列來匹配行,這樣的列稱為最左前綴。
對于使用 InnoDB 存儲引擎的表來說,記錄會按照一定的順序保存。如果有明確的主鍵定義,那么會按照主鍵的順序進行保存;如果沒有主鍵,但是有唯一索引,那么就按照唯一索引的順序進行保存。如果既沒有主鍵又沒有唯一索引,那么表中會自動生成一個內(nèi)部列,按照這個列的順序進行保存。一般來說,使用主鍵的順序是最快的。
刪除不再使用或者很少使用的索引。
五、視圖
MySQL 從 5.0 開始就提供了視圖功能,下面我們對視圖功能進行介紹。
1、什么是視圖
視圖的英文名稱是** view**,它是一種虛擬存在的表。視圖對于用戶來說是透明的,它并不在數(shù)據(jù)庫中實際存在,視圖是使用數(shù)據(jù)庫行和列動態(tài)組成的表,那么視圖相對于數(shù)據(jù)庫表來說,優(yōu)勢體現(xiàn)在哪里?
視圖相對于普通的表來說,優(yōu)勢包含下面這幾項:
使用視圖可以簡化操作:使用視圖我們不用關(guān)注表結(jié)構(gòu)的定義,我們可以把經(jīng)常使用的數(shù)據(jù)集合定義成視圖,這樣能夠簡化操作。
安全性:用戶對視圖不可以隨意的更改和刪除,可以保證數(shù)據(jù)的安全性。
數(shù)據(jù)獨立性:一旦視圖的結(jié)構(gòu) 確定了, 可以屏蔽表結(jié)構(gòu)變化對用戶的影響, 數(shù)據(jù)庫表增加列對視圖沒有影響;具有一定的獨立性。
2、對視圖的操作
視圖的操作包括創(chuàng)建或者修改視圖、刪除視圖以及查看視圖定義。
(1)創(chuàng)建或修改視圖
使用** create view **來創(chuàng)建視圖
為了演示功能,我們先創(chuàng)建一張表** product **表,有三個字段,id,name,price,下面是建表語句
create table product(id int(11),name varchar(20),price float(10,2));
然后我們向其中插入幾條數(shù)據(jù)
insert into product values(1, "apple","3.5"),(2,"banana","4.2"),(3,"melon","1.2");
插入完成后的表結(jié)構(gòu)如下
然后我們創(chuàng)建視圖
create view v1 as select * from product;
然后我們查看一下 v1 視圖的結(jié)構(gòu)
可以看到我們把 product 中的數(shù)據(jù)放在了視圖中,也相當(dāng)于是創(chuàng)建了一個 product 的副本,只不過這個副本跟表無關(guān)。
視圖使用
show tables;
也能看到所有的視圖。
刪除視圖的語法是
drop view v1;
能夠直接進行刪除。
視圖還有其他操作,比如查詢操作
你還可以使用
describe v1;
查看表結(jié)構(gòu)
更新視圖
update v1 set name = "grape" where id = 1;
六、存儲過程
MySQL 從 5.0 開始起就支持存儲過程和函數(shù)了。
那么什么是存儲過程呢?
「存儲過程是在數(shù)據(jù)庫系統(tǒng)中完成一組特定功能的 SQL 語句集」,它存儲在數(shù)據(jù)庫系統(tǒng)中,一次編譯后永久有效。那么使用存儲過程有什么優(yōu)點呢?
使用存儲過程具有可封裝性,能夠隱藏復(fù)雜的 SQL 邏輯。
存儲過程可以接收參數(shù),并返回結(jié)果。
存儲過程性能非常高,一般用于批量執(zhí)行語句。
使用存儲過程有什么缺點?
存儲過程編寫復(fù)雜。
存儲過程對數(shù)據(jù)庫的依賴性比較強,可移植性比較差。
1、存儲過程使用
(1)存儲過程創(chuàng)建
在認(rèn)識到存儲過程是什么之后,我們就來使用一下存儲過程,這里需要先了解一個小技巧,也就是 delimiter 的用法,delimiter 用于自定義結(jié)束符,什么意思呢,如果你使用
delimiter $$
的話,那么你在 sql 語句末使用** ; **是不能使 SQL 語句執(zhí)行的,不信?我們可以看下
可以看到,我們在 SQL 語句的行末使用了** ; **但是我們卻沒有看到執(zhí)行結(jié)果。下面我們使用
delimiter ;
恢復(fù)默認(rèn)的執(zhí)行條件再來看下
我們創(chuàng)建存儲過程首先要把** ; **替換為 $$,下面是一個存儲過程的創(chuàng)建語句
mysql> delimiter $$
存儲過程實際上是一種函數(shù),所以創(chuàng)建完畢后,我們可以使用** call **方法來調(diào)用這個存儲過程
因為我們上面定義了使用 delimiter $$ 來結(jié)尾,所以這里也應(yīng)該使用。
存儲過程也可以接受參數(shù),比如我們定義一種接收參數(shù)的情況
然后我們使用 **call **調(diào)用這個存儲過程
可以看到,當(dāng)我們調(diào)用 id = 2 的時候,存儲過程的 SQL 語句相當(dāng)于是
select * from product where id = 2;
所以只查詢出 id = 2 的結(jié)果。
(2)存儲過程刪除
一次只能刪除一個存儲過程,刪除存儲過程的語法如下
drop procedure sp_product ;
直接使用 sp_product 就可以了,不用加 ()。
(3)存儲過程查看
存儲過程創(chuàng)建后,用戶可能需要需要查看存儲過程的狀態(tài)等信息,便于了解存儲過程的基本情況
我們可以使用
show create procedure proc_name;
2、變量的使用
在 MySQL 中,變量可分為兩大類,即系統(tǒng)變量和用戶變量,這是一種粗略的分法。但是根據(jù)實際應(yīng)用又被細(xì)化為四種類型,即局部變量、用戶變量、會話變量和全局變量。
(1)用戶變量
用戶變量是基于會話變量實現(xiàn)的,可以暫存,用戶變量與連接有關(guān),也就是說一個客戶端定義的變量不能被其他客戶端使用看到。當(dāng)客戶端退出時,鏈接會自動釋放。我們可以使用 set 語句設(shè)置一個變量
set @myId = "cxuan";
然后使用 **select **查詢條件可以查詢出我們剛剛設(shè)置的用戶變量
用戶變量是和客戶端有關(guān)系,當(dāng)我們退出后,這個變量會自動消失,現(xiàn)在我們退出客戶端
exit
現(xiàn)在我們重新登陸客戶端,再次使用** select** 條件查詢
發(fā)現(xiàn)已經(jīng)沒有這個** @myId **了。
(2)局部變量
MySQL 中的局部變量與 Java 很類似 ,Java 中的局部變量是 Java 所在的方法或者代碼塊,而 MySQL 中的局部變量作用域是所在的存儲過程。MySQL 局部變量使用** declare** 來聲明。
(3)會話變量
服務(wù)器會為每個連接的客戶端維護一個會話變量。可以使用
show session variables;
顯示所有的會話變量。
我們可以手動設(shè)置會話變量
set session auto_increment_increment=1;
或者使用
set @@session.auto_increment_increment=2;
然后進行查詢,查詢會話變量使用
或者使用
(4)全局變量
當(dāng)服務(wù)啟動時,它將所有全局變量初始化為默認(rèn)值。其作用域為 server 的整個生命周期。
可以使用
show global variables;
查看全局變量
可以使用下面這兩種方式設(shè)置全局變量
set global sql_warnings=ON; -- global不能省略
查詢?nèi)肿兞繒r,可以使用
或者是
3、MySQL 流程語句介紹
MySQL 支持下面這些控制語句
- IF
IF 用于實現(xiàn)邏輯判斷,滿足不同條件執(zhí)行不同的 SQL 語句
IF ... THEN ...
- CASE
CASE 實現(xiàn)比 IF 稍微復(fù)雜,語法如下
CASE ...
CASE 語句也可以使用 IF 來完成
- LOOP
LOOP 用于實現(xiàn)簡單的循環(huán)
label:LOOP
如果 **... **中不寫 SQL 語句的話,那么就是一個簡單的死循環(huán)語句
- LEAVE
用來表示從標(biāo)注的流程構(gòu)造中退出,通常和 BEGIN...END 或者循環(huán)一起使用
- ITERATE
ITERATE 語句必須用在循環(huán)中,作用是跳過當(dāng)前循環(huán)的剩下的語句,直接進入下一輪循環(huán)。
- REPEAT
帶有條件的循環(huán)控制語句,當(dāng)滿足條件的時候退出循環(huán)。
REPEAT
- WHILE
WHILE 語句表示的含義和 REPEAT 相差無幾,WHILE 循環(huán)和 REPEAT 循環(huán)的區(qū)別在于:WHILE 是滿足條件才執(zhí)行循環(huán),REPEAT 是滿足條件退出循環(huán);
七、觸發(fā)器
MySQL 從 5.0 開始支持觸發(fā)器,觸發(fā)器一般作用在表上,在滿足定義條件時觸發(fā),并執(zhí)行觸發(fā)器中定義的語句集合,下面我們就來一起認(rèn)識一下觸發(fā)器。
舉個例子來認(rèn)識一下觸發(fā)器:比如你有一個日志表和金額表,你每錄入一筆金額就要進行日志表的記錄,你會怎么樣?同時在金額表和日志表插入數(shù)據(jù)嗎?如果有了觸發(fā)器,你可以直接在金額表錄入數(shù)據(jù),日志表會自動插入一條日志記錄,當(dāng)然,觸發(fā)器不僅只有新增操作,還有更新和刪除操作。
1、創(chuàng)建觸發(fā)器我們可以用如下的方式創(chuàng)建觸發(fā)器
create trigger triggername triggertime triggerevent on tbname for each row triggerstmt
上面涉及到幾個參數(shù),我知道你有點懵逼,解釋一下。
- t****riggername:這個指的就是觸發(fā)器的名字。
- triggertime:這個指的就是觸發(fā)器觸發(fā)時機,是** BEFORE** 還是 AFTER。
- triggerevent: 這個指的就是觸發(fā)器觸發(fā)事件,一共有三種事件:「INSERT、UPDATE 或者 DELETE」。
- tbname:這個參數(shù)指的是觸發(fā)器創(chuàng)建的表名,在哪個表上創(chuàng)建
- **triggerstmt: **觸發(fā)器的程序體,也就是 SQL 語句
所以,可以創(chuàng)建六種觸發(fā)器「BEFORE INSERT、AFTER INSERT、BEFORE UPDATE、AFTER UPDATE、BEFORE DELETE、AFTER DELETE」上面的** for each now** 表示任何一條記錄上的操作都會觸發(fā)觸發(fā)器。下面我們通過一個例子來演示一下觸發(fā)器的操作我們還是用上面的 procuct 表做例子,我們創(chuàng)建一個 product_info 產(chǎn)品信息表。
create table product_info(p_info varchar(20));
然后我們創(chuàng)建一個 trigger
我們在 product 表中插入一條數(shù)據(jù)
insert into product values(4,"pineapple",15.3);
我們進行 select 查詢,可以看到現(xiàn)在 product 表中有四條數(shù)據(jù)
我們沒有向 product_info 表中插入數(shù)據(jù),現(xiàn)在我們來看一下 product_info 表中,我們預(yù)想到是有數(shù)據(jù)的,具體來看下
這條數(shù)據(jù)是什么時候插入的呢?我們在創(chuàng)建觸發(fā)器 tg_pinfo 的時候插入了的這條數(shù)據(jù)。2、刪除觸發(fā)器觸發(fā)器可以使用** drop** 進行刪除,具體刪除語法如下
drop trigger tg_pinfo;
和刪除表的語法是一樣的3、查看觸發(fā)器我們經(jīng)常會查看觸發(fā)器,可以通過執(zhí)行 show triggers 命令查看觸發(fā)器的狀態(tài)、語法等信息。另一種查詢方式是查詢表中的 information_schema.triggers 表,這個可以查詢指定觸發(fā)器的指定信息,操作起來方便很多4、觸發(fā)器的作用
- 在添加一條數(shù)據(jù)前,檢查數(shù)據(jù)是否合理,例如檢查郵件格式是否正確;
- 刪除數(shù)據(jù)后,相當(dāng)于數(shù)據(jù)備份的作用;
- 可以記錄數(shù)據(jù)庫的操作日志,也可以作為表的執(zhí)行軌跡;
注意:觸發(fā)器的使用有兩個限制:
- 觸發(fā)程序不能調(diào)用將數(shù)據(jù)返回客戶端的存儲程序。也不能使用 CALL 語句的動態(tài) SQL 語句;
- 不能在觸發(fā)器中開始和結(jié)束語句,例如 START TRANSACTION。
以下文章來源于Java建設(shè)者 ,作者cxuan
https://mp.weixin.qq.com/s/EXbMgT0T3cXZ0u-4lvMDbQ