47 張圖帶你 MySQL 進階!!!

我們在 MySQL 入門篇主要介紹了基本的 SQL 命令、數據類型和函數,在局部以上知識後,你就可以進行 MySQL 的開發工作了,但是如果要成為一個合格的開發人員,你還要具備一些更高級的技能,下面我們就來探討一下 MySQL 都需要哪些高級的技能

MySQL 存儲引擎

存儲引擎概述

資料庫最核心的一點就是用來存儲數據,數據存儲就避免不了和磁碟打交道。那麼數據以哪種方式進行存儲,如何存儲是存儲的關鍵所在。所以存儲引擎就相當於是數據存儲的發動機,來驅動數據在磁碟層面進行存儲。

MySQL 的架構可以按照三層模式來理解

存儲引擎也是 MySQL 的組建,它是一種軟體,它所能做的和支援的功能主要有

  • 並發
  • 支援事務
  • 完整性約束
  • 物理存儲
  • 支援索引
  • 性能幫助

MySQL 默認支援多種存儲引擎,來適用不同資料庫應用,用戶可以根據需要選擇合適的存儲引擎,下面是 MySQL 支援的存儲引擎

  • MyISAM
  • InnoDB
  • BDB
  • MEMORY
  • MERGE
  • EXAMPLE
  • NDB Cluster
  • ARCHIVE
  • CSV
  • BLACKHOLE
  • FEDERATED

默認情況下,如果創建表不指定存儲引擎,會使用默認的存儲引擎,如果要修改默認的存儲引擎,那麼就可以在參數文件中設置 default-table-type,能夠查看當前的存儲引擎

show variables like 'table_type';

奇怪,為什麼沒有了呢?網上求證一下,在 5.5.3 取消了這個參數

可以通過下面兩種方法查詢當前資料庫支援的存儲引擎

show engines \g

在創建新表的時候,可以通過增加 ENGINE 關鍵字設置新建表的存儲引擎。

create table cxuan002(id int(10),name varchar(20)) engine = MyISAM;

上圖我們指定了 MyISAM 的存儲引擎。

如果你不知道表的存儲引擎怎麼辦?你可以通過 show create table 來查看

如果不指定存儲引擎的話,從MySQL 5.1 版本之後,MySQL 的默認內置存儲引擎已經是 InnoDB了。建一張表看一下

如上圖所示,我們沒有指定默認的存儲引擎,下面查看一下表

可以看到,默認的存儲引擎是 InnoDB

如果你的存儲引擎想要更換,可以使用

alter table cxuan003 engine = myisam;

來更換,更換完成後回顯示 0 rows affected ,但其實已經操作成功

我們使用 show create table 查看一下表的 sql 就知道

存儲引擎特性

下面會介紹幾個常用的存儲引擎以及它的基本特性,這些存儲引擎是 **MyISAM、InnoDB、MEMORY 和 MERGE **

MyISAM

在 5.1 版本之前,MyISAM 是 MySQL 的默認存儲引擎,MyISAM 並發性比較差,使用的場景比較少,主要特點是

  • 不支援事務操作,ACID 的特性也就不存在了,這一設計是為了性能和效率考慮的。

  • 不支援外鍵操作,如果強行增加外鍵,MySQL 不會報錯,只不過外鍵不起作用。

  • MyISAM 默認的鎖粒度是表級鎖,所以並發性能比較差,加鎖比較快,鎖衝突比較少,不太容易發生死鎖的情況。

  • MyISAM 會在磁碟上存儲三個文件,文件名和表名相同,擴展名分別是 .frm(存儲表定義).MYD(MYData,存儲數據)MYI(MyIndex,存儲索引)。這裡需要特別注意的是 MyISAM 只快取索引文件,並不快取數據文件。

  • MyISAM 支援的索引類型有 全局索引(Full-Text)B-Tree 索引R-Tree 索引

    Full-Text 索引:它的出現是為了解決針對文本的模糊查詢效率較低的問題。

    B-Tree 索引:所有的索引節點都按照平衡樹的數據結構來存儲,所有的索引數據節點都在葉節點

    R-Tree索引:它的存儲方式和 B-Tree 索引有一些區別,主要設計用於存儲空間和多維數據的欄位做索引,目前的 MySQL 版本僅支援 geometry 類型的欄位作索引,相對於 BTREE,RTREE 的優勢在於範圍查找。

  • 資料庫所在主機如果宕機,MyISAM 的數據文件容易損壞,而且難以恢復。

  • 增刪改查性能方面:SELECT 性能較高,適用於查詢較多的情況

InnoDB

自從 MySQL 5.1 之後,默認的存儲引擎變成了 InnoDB 存儲引擎,相對於 MyISAM,InnoDB 存儲引擎有了較大的改變,它的主要特點是

  • 支援事務操作,具有事務 ACID 隔離特性,默認的隔離級別是可重複讀(repetable-read)、通過MVCC(並發版本控制)來實現的。能夠解決臟讀不可重複讀的問題。
  • InnoDB 支援外鍵操作。
  • InnoDB 默認的鎖粒度行級鎖,並發性能比較好,會發生死鎖的情況。
  • 和 MyISAM 一樣的是,InnoDB 存儲引擎也有 .frm文件存儲表結構 定義,但是不同的是,InnoDB 的表數據與索引數據是存儲在一起的,都位於 B+ 數的葉子節點上,而 MyISAM 的表數據和索引數據是分開的。
  • InnoDB 有安全的日誌文件,這個日誌文件用於恢復因資料庫崩潰或其他情況導致的數據丟失問題,保證數據的一致性。
  • InnoDB 和 MyISAM 支援的索引類型相同,但具體實現因為文件結構的不同有很大差異。
  • 增刪改查性能方面,果執行大量的增刪改操作,推薦使用 InnoDB 存儲引擎,它在刪除操作時是對行刪除,不會重建表。

MEMORY

MEMORY 存儲引擎使用存在記憶體中的內容來創建表。每個 MEMORY 表實際只對應一個磁碟文件,格式是 .frm。 MEMORY 類型的表訪問速度很快,因為其數據是存放在記憶體中。默認使用 HASH 索引

MERGE

MERGE 存儲引擎是一組 MyISAM 表的組合,MERGE 表本身沒有數據,對 MERGE 類型的表進行查詢、更新、刪除的操作,實際上是對內部的 MyISAM 表進行的。MERGE 表在磁碟上保留兩個文件,一個是 .frm 文件存儲表定義、一個是 .MRG 文件存儲 MERGE 表的組成等。

選擇合適的存儲引擎

在實際開發過程中,我們往往會根據應用特點選擇合適的存儲引擎。

  • MyISAM:如果應用程式通常以檢索為主,只有少量的插入、更新和刪除操作,並且對事物的完整性、並發程度不是很高的話,通常建議選擇 MyISAM 存儲引擎。
  • InnoDB:如果使用到外鍵、需要並發程度較高,數據一致性要求較高,那麼通常選擇 InnoDB 引擎,一般互聯網大廠對並發和數據完整性要求較高,所以一般都使用 InnoDB 存儲引擎。
  • MEMORY:MEMORY 存儲引擎將所有數據保存在記憶體中,在需要快速定位下能夠提供及其迅速的訪問。MEMORY 通常用於更新不太頻繁的小表,用於快速訪問取得結果。
  • MERGE:MERGE 的內部是使用 MyISAM 表,MERGE 表的優點在於可以突破對單個 MyISAM 表大小的限制,並且通過將不同的表分布在多個磁碟上, 可以有效地改善 MERGE 表的訪問效率。

選擇合適的數據類型

我們會經常遇見的一個問題就是,在建表時如何選擇合適的數據類型,通常選擇合適的數據類型能夠提高性能、減少不必要的麻煩,下面我們就來一起探討一下,如何選擇合適的數據類型。

CHAR 和 VARCHAR 的選擇

char 和 varchar 是我們經常要用到的兩個存儲字元串的數據類型,char 一般存儲定長的字元串,它屬於固定長度的字元類型,比如下面

char(5) 存儲位元組
‘ ‘ 5個位元組
‘cx’ ‘cx ‘ 5個位元組
‘cxuan’ ‘cxuan’ 5個位元組
‘cxuan007’ ‘cxuan’ 5個位元組

可以看到,不管你的值寫的是什麼,一旦指定了 char 字元的長度,如果你的字元串長度不夠指定字元的長度的話,那麼就用空格來填補,如果超過字元串長度的話,只存儲指定字元長度的字元。

這裡注意一點:如果 MySQL 使用了非 嚴格模式的話,上面表格最後一行是可以存儲的。如果 MySQL 使用了 嚴格模式 的話,那麼表格上面最後一行存儲會報錯。

如果使用了 varchar 字元類型,我們來看一下例子

varchar(5) 存儲位元組
1個位元組
‘cx’ ‘cx ‘ 3個位元組
‘cxuan’ ‘cxuan’ 6個位元組
‘cxuan007’ ‘cxuan’ 6個位元組

可以看到,如果使用 varchar 的話,那麼存儲的位元組將根據實際的值進行存儲。你可能會疑惑為什麼 varchar 的長度是 5 ,但是卻需要存儲 3 個位元組或者 6 個位元組,這是因為使用 varchar 數據類型進行存儲時,默認會在最後增加一個字元串長度,佔用1個位元組(如果列聲明的長度超過255,則使用兩個位元組)。varchar 不會填充空餘的字元串。

一般使用 char 來存儲定長的字元串,比如身份證號、手機號、郵箱等;使用 varchar 來存儲不定長的字元串。由於 char 長度是固定的,所以它的處理速度要比 VARCHAR 快很多,但是缺點是浪費存儲空間,但是隨著 MySQL 版本的不斷演進,varchar 數據類型的性能也在不斷改進和提高,所以在許多應用中,VARCHAR 類型更多的被使用。

在 MySQL 中,不同的存儲引擎對 CHAR 和 VARCHAR 的使用原則也有不同

  • MyISAM:建議使用固定長度的數據列替代可變長度的數據列,也就是 CHAR
  • MEMORY:使用固定長度進行處理、CHAR 和 VARCHAR 都會被當作 CHAR 處理
  • InnoDB:建議使用 VARCHAR 類型

TEXT 與 BLOB

一般在保存較少的文本的時候,我們會選擇 CHAR 和 VARCHAR,在保存大數據量的文本時,我們往往選擇 TEXT 和 BLOB;TEXT 和 BLOB 的主要差別是 BLOB 能夠保存二進位數據;而 TEXT 只能保存字元數據,TEXT 往下細分有

  • TEXT
  • MEDIUMTEXT
  • LONGTEXT

BLOB 往下細分有

  • BLOB
  • MEDIUMBLOB
  • LONGBLOB

三種,它們最主要的區別就是存儲文本長度不同和存儲位元組不同,用戶應該根據實際情況選擇滿足需求的最小存儲類型,下面主要對 BLOB 和 TEXT 存在一些問題進行介紹

TEXT 和 BLOB 在刪除數據後會存在一些性能上的問題,為了提高性能,建議使用 OPTIMIZE TABLE 功能對錶進行碎片整理。

也可以使用合成索引來提高文本欄位(BLOB 和 TEXT)的查詢性能。合成索引就是根據大文本(BLOB 和 TEXT)欄位的內容建立一個散列值,把這個值存在對應列中,這樣就能夠根據散列值查找到對應的數據行。一般使用散列演算法比如 md5() 和 SHA1() ,如果散列演算法生成的字元串帶有尾部空格,就不要把它們存在 CHAR 和 VARCHAR 中,下面我們就來看一下這種使用方式

首先創建一張表,表中記錄 blob 欄位和 hash 值

向 cxuan005 中插入數據,其中 hash 值作為 info 的散列值。

然後再插入兩條數據

插入一條 info 為 cxuan005 的數據

如果想要查詢 info 為 cxuan005 的數據,可以通過查詢 hash 列來進行查詢

這是合成索引的例子,如果要對 BLOB 進行模糊查詢的話,就要使用前綴索引。

其他優化 BLOB 和 TEXT 的方式:

  • 非必要的時候不要檢索 BLOB 和 TEXT 索引
  • 把 BLOB 或 TEXT 列分離到單獨的表中。

浮點數和定點數的選擇

浮點數指的就是含有小數的值,浮點數插入到指定列中超過指定精度後,浮點數會四捨五入,MySQL 中的浮點數指的就是 floatdouble,定點數指的是 decimal,定點數能夠更加精確的保存和顯示數據。下面通過一個示例講解一下浮點數精確性問題

首先創建一個表 cxuan006 ,只為了測試浮點數問題,所以這裡我們選擇的數據類型是 float

然後分別插入兩條數據

然後執行查詢,可以看到查詢出來的兩條數據執行的舍入不同

為了清晰的看清楚浮點數與定點數的精度問題,再來看一個例子

先修改 cxuan006 的兩個欄位為相同的長度和小數位數

然後插入兩條數據

執行查詢操作,可以發現,浮點數相較於定點數來說,會產生誤差

日期類型選擇

在 MySQL 中,用來表示日期類型的有 DATE、TIME、DATETIME、TIMESTAMP,在

138 張圖帶你 MySQL 入門

這篇文中介紹過了日期類型的區別,我們這裡就不再闡述了。下面主要介紹一下選擇

  • TIMESTAMP 和時區相關,更能反映當前時間,如果記錄的日期需要讓不同時區的人使用,最好使用 TIMESTAMP。
  • DATE 用於表示年月日,如果實際應用值需要保存年月日的話就可以使用 DATE。
  • TIME 用於表示時分秒,如果實際應用值需要保存時分秒的話就可以使用 TIME。
  • YEAR 用於表示年份,YEAR 有 2 位(最好使用4位)和 4 位格式的年。 默認是4位。如果實際應用只保存年份,那麼用 1 bytes 保存 YEAR 類型完全可以。不但能夠節約存儲空間,還能提高表的操作效率。

MySQL 字符集

下面來認識一下 MySQL 字符集,簡單來說字符集就是一套文字元號和編碼、比較規則的集合。1960 年美國標準化組織 ANSI 發布了第一個電腦字符集,就是著名的 ASCII(American Standard Code for Information Interchange) 。自從 ASCII 編碼後,每個國家、國際組織都研究了一套自己的字符集,比如 ISO-8859-1GBK 等。

但是每個國家都使用自己的字符集為移植性帶來了很大的困難。所以,為了統一字元編碼,國際標準化組織(ISO) 指定了統一的字元標準 – Unicode 編碼,它容納了幾乎所有的字元編碼。下面是一些常見的字元編碼

字符集 是否定長 編碼方式
ASCII 單位元組 7 位編碼
ISO-8859-1 單位元組 8 位編碼
GBK 雙位元組編碼
UTF-8 1 – 4 位元組編碼
UTF-16 2 位元組或 4 位元組編碼
UTF-32 4 位元組編碼

對資料庫來說,字符集是很重要的,因為資料庫存儲的數據大多數都是各種文字,字符集對資料庫的存儲、性能、系統的移植來說都非常重要。

MySQL 支援多種字符集,可以使用 show character set; 來查看所有可用的字符集

或者使用

select character_set_name, default_collate_name, description, maxlen from information_schema.character_sets;

來查看。

使用 information_schema.character_set 來查看字符集和校對規則。

索引的設計和使用

我們上面介紹到了索引的幾種類型並對不同的索引類型做了闡述,闡明了優缺點等等,下面我們從設計角度來聊一下索引,關於索引,你必須要知道的一點就是:索引是資料庫用來提高性能的最常用工具

索引概述

所有的 MySQL 類型都可以進行索引,對相關列使用索引是提高 SELECT 查詢性能的最佳途徑。MyISAM 和 InnoDB 都是使用 BTREE 作為索引,MySQL 5 不支援函數索引,但是支援 前綴索引

前綴索引顧名思義就是對列欄位的前綴做索引,前綴索引的長度和存儲引擎有關係。MyISAM 前綴索引的長度支援到 1000 位元組,InnoDB 前綴索引的長度支援到 767 位元組,索引值重複性越低,查詢效率也就越高。

在 MySQL 中,主要有下面這幾種索引

  • 全局索引(FULLTEXT):全局索引,目前只有 MyISAM 引擎支援全局索引,它的出現是為了解決針對文本的模糊查詢效率較低的問題,並且只限於 CHAR、VARCHAR 和 TEXT 列。
  • 哈希索引(HASH):哈希索引是 MySQL 中用到的唯一 key-value 鍵值對的數據結構,很適合作為索引。HASH 索引具有一次定位的好處,不需要像樹那樣逐個節點查找,但是這種查找適合應用於查找單個鍵的情況,對於範圍查找,HASH 索引的性能就會很低。默認情況下,MEMORY 存儲引擎使用 HASH 索引,但也支援 BTREE 索引。
  • B-Tree 索引:B 就是 Balance 的意思,BTree 是一種平衡樹,它有很多變種,最常見的就是 B+ Tree,它被 MySQL 廣泛使用。
  • R-Tree 索引:R-Tree 在 MySQL 很少使用,僅支援 geometry 數據類型,支援該類型的存儲引擎只有MyISAM、BDb、InnoDb、NDb、Archive幾種,相對於 B-Tree 來說,R-Tree 的優勢在於範圍查找。

索引可以在創建表的時候進行創建,也可以單獨創建,下面我們採用單獨創建的方式,我們在 cxuan004 上創建前綴索引

我們使用 explain 進行分析,可以看到 cxuan004 使用索引的情況

如果不想使用索引,可以刪除索引,索引的刪除語法是

索引設計原則

創建索引的時候,要盡量考慮以下原則,便於提升索引的使用效率。

  • 選擇索引位置,選擇索引最合適的位置是出現在 where 語句中的列,而不是 select 關鍵字後的選擇列表中的列。
  • 選擇使用唯一索引,顧名思義,唯一索引的值是唯一的,可以更快速的確定某條記錄,例如學生的學號就適合使用唯一性索引,而學生的性別則不適合使用,因為不管搜索哪個值,都差不多有一半的行。
  • 為經常使用的欄位建立索引,如果某個欄位經常用作查詢條件,那麼這個欄位的查詢速度在極大程度上影響整個表的查詢速度,因此為這樣的欄位建立索引,可以提高整個表的查詢速度。
  • 不要過度索引,限制索引數目,索引的數目不是越多越好,每個索引都會佔據磁碟空間,索引越多,需要的磁碟空間就越大。
  • 盡量使用前綴索引,如果索引的值很長,那麼查詢速度會受到影響,這個時候應該使用前綴索引,對列的某幾個字元進行索引,可以提高檢索效率。
  • 利用最左前綴,在創建一個 n 列的索引時,實際上是創建了 MySQL 可利用的 n 個索引。多列索引可以起到幾個索引的作用,利用索引最左邊的列來匹配行,這樣的列稱為最左前綴。
  • 對於使用 InnoDB 存儲引擎的表來說,記錄會按照一定的順序保存。如果有明確的主鍵定義,那麼會按照主鍵的順序進行保存;如果沒有主鍵,但是有唯一索引,那麼就按照唯一索引的順序進行保存。如果既沒有主鍵又沒有唯一索引,那麼表中會自動生成一個內部列,按照這個列的順序進行保存。一般來說,使用主鍵的順序是最快的
  • 刪除不再使用或者很少使用的索引

視圖

MySQL 從 5.0 開始就提供了視圖功能,下面我們對視圖功能進行介紹。

什麼是視圖

視圖的英文名稱是 view,它是一種虛擬存在的表。視圖對於用戶來說是透明的,它並不在資料庫中實際存在,視圖是使用資料庫行和列動態組成的表,那麼視圖相對於資料庫表來說,優勢體現在哪裡?

視圖相對於普通的表來說,優勢包含下面這幾項

  • 使用視圖可以簡化操作:使用視圖我們不用關注表結構的定義,我們可以把經常使用的數據集合定義成視圖,這樣能夠簡化操作。
  • 安全性:用戶對視圖不可以隨意的更改和刪除,可以保證數據的安全性。
  • 數據獨立性:一旦視圖的結構 確定了, 可以屏蔽表結構變化對用戶的影響, 資料庫表增加列對視圖沒有影響;具有一定的獨立性

對視圖的操作

視圖的操作包括創建或者修改視圖、刪除視圖以及查看視圖定義。

創建或修改視圖

使用 create view 來創建視圖

為了演示功能,我們先創建一張表 product 表,有三個欄位,id,name,price,下面是建表語句

create table product(id int(11),name varchar(20),price float(10,2));

然後我們向其中插入幾條數據

insert into product values(1, "apple","3.5"),(2,"banana","4.2"),(3,"melon","1.2");

插入完成後的表結構如下

然後我們創建視圖

create view v1 as select * from product;

然後我們查看一下 v1 視圖的結構

可以看到我們把 product 中的數據放在了視圖中,也相當於是創建了一個 product 的副本,只不過這個副本跟表無關。

視圖使用

show tables;

也能看到所有的視圖。

刪除視圖的語法是

drop view v1;

能夠直接進行刪除。

視圖還有其他操作,比如查詢操作

你還可以使用

describe v1;

查看錶結構

更新視圖

update v1 set name = "grape" where id = 1;

存儲過程

MySQL 從 5.0 開始起就支援存儲過程和函數了。

那麼什麼是存儲過程呢?

存儲過程是在資料庫系統中完成一組特定功能的 SQL 語句集,它存儲在資料庫系統中,一次編譯後永久有效。那麼使用存儲過程有什麼優點呢?

  • 使用存儲過程具有可封裝性,能夠隱藏複雜的 SQL 邏輯。
  • 存儲過程可以接收參數,並返回結果
  • 存儲過程性能非常高,一般用於批量執行語句

使用存儲過程有什麼缺點?

  • 存儲過程編寫複雜
  • 存儲過程對資料庫的依賴性比較強,可移植性比較差

存儲過程使用

存儲過程創建

在認識到存儲過程是什麼之後,我們就來使用一下存儲過程,這裡需要先了解一個小技巧,也就是 delimiter 的用法,delimiter 用於自定義結束符,什麼意思呢,如果你使用

delimiter $$

的話,那麼你在 sql 語句末使用 ; 是不能使 SQL 語句執行的,不信?我們可以看下

可以看到,我們在 SQL 語句的行末使用了 ; 但是我們卻沒有看到執行結果。下面我們使用

delimiter ;

恢復默認的執行條件再來看下

我們創建存儲過程首先要把 ; 替換為 $$,下面是一個存儲過程的創建語句

mysql> delimiter $$
mysql> create procedure sp_product()
    -> begin
    -> select * from product;
    -> end $$

存儲過程實際上是一種函數,所以創建完畢後,我們可以使用 call 方法來調用這個存儲過程

因為我們上面定義了使用 delimiter $$ 來結尾,所以這裡也應該使用。

存儲過程也可以接受參數,比如我們定義一種接收參數的情況

然後我們使用 call 調用這個存儲過程

可以看到,當我們調用 id = 2 的時候,存儲過程的 SQL 語句相當於是

select * from product where id = 2;

所以只查詢出 id = 2 的結果。

存儲過程刪除

一次只能刪除一個存儲過程,刪除存儲過程的語法如下

drop procedure sp_product ;

直接使用 sp_product 就可以了,不用加 ()

存儲過程查看

存儲過程創建後,用戶可能需要需要查看存儲過程的狀態等資訊,便於了解存儲過程的基本情況

我們可以使用

show create procedure proc_name;

變數的使用

在 MySQL 中,變數可分為兩大類,即系統變數用戶變數,這是一種粗略的分法。但是根據實際應用又被細化為四種類型,即局部變數、用戶變數、會話變數和全局變數。

用戶變數

用戶變數是基於會話變數實現的,可以暫存,用戶變數與連接有關,也就是說一個客戶端定義的變數不能被其他客戶端使用看到。當客戶端退出時,鏈接會自動釋放。我們可以使用 set 語句設置一個變數

set @myId = "cxuan";

然後使用 select 查詢條件可以查詢出我們剛剛設置的用戶變數

用戶變數是和客戶端有關係,當我們退出後,這個變數會自動消失,現在我們退出客戶端

exit

現在我們重新登陸客戶端,再次使用 select 條件查詢

發現已經沒有這個 @myId 了。

局部變數

MySQL 中的局部變數與 Java 很類似 ,Java 中的局部變數是 Java 所在的方法或者程式碼塊,而 MySQL 中的局部變數作用域是所在的存儲過程。MySQL 局部變數使用 declare 來聲明。

會話變數

伺服器會為每個連接的客戶端維護一個會話變數。可以使用

show session variables;

顯示所有的會話變數。

我們可以手動設置會話變數

set session auto_increment_increment=1;

或者使用

set @@session.auto_increment_increment=2;

然後進行查詢,查詢會話變數使用

或者使用

全局變數

當服務啟動時,它將所有全局變數初始化為默認值。其作用域為 server 的整個生命周期。

可以使用

show global variables;

查看全局變數

可以使用下面這兩種方式設置全局變數

set global sql_warnings=ON;        -- global不能省略

/** 或者 **/

set @@global.sql_warnings=OFF;

查詢全局變數時,可以使用

或者是

MySQL 流程語句介紹

MySQL 支援下面這些控制語句

  • IF

IF 用於實現邏輯判斷,滿足不同條件執行不同的 SQL 語句

IF ... THEN ...
  • CASE

CASE 實現比 IF 稍微複雜,語法如下

CASE ...
	WHEN ... THEN...
	...
END CASE

CASE 語句也可以使用 IF 來完成

  • LOOP

LOOP 用於實現簡單的循環

label:LOOP
     ...
END LOOP label;

如果 ... 中不寫 SQL 語句的話,那麼就是一個簡單的死循環語句

  • LEAVE

用來表示從標註的流程構造中退出,通常和 BEGIN…END 或者循環一起使用

  • ITERATE

ITERATE 語句必須用在循環中,作用是跳過當前循環的剩下的語句,直接進入下一輪循環。

  • REPEAT

帶有條件的循環控制語句,當滿足條件的時候退出循環。

REPEAT
   ...
   UNTIL
END REPEAT;
  • WHILE

WHILE 語句表示的含義和 REPEAT 相差無幾,WHILE 循環和 REPEAT 循環的區別在於:WHILE 是滿足條件才執行循環,REPEAT 是滿足條件退出循環;

觸發器

MySQL 從 5.0 開始支援觸發器,觸發器一般作用在表上,在滿足定義條件時觸發,並執行觸發器中定義的語句集合,下面我們就來一起認識一下觸發器。

舉個例子來認識一下觸發器:比如你有一個日誌表和金額表,你每錄入一筆金額就要進行日誌表的記錄,你會怎麼樣?同時在金額表和日誌表插入數據嗎?如果有了觸發器,你可以直接在金額表錄入數據,日誌表會自動插入一條日誌記錄,當然,觸發器不僅只有新增操作,還有更新和刪除操作。

創建觸發器

我們可以用如下的方式創建觸發器

create trigger triggername triggertime triggerevent on tbname for each row triggerstmt

上面涉及到幾個參數,我知道你有點懵逼,解釋一下。

  • triggername:這個指的就是觸發器的名字
  • triggertime:這個指的就是觸發器觸發時機,是 BEFORE 還是 AFTER
  • triggerevent: 這個指的就是觸發器觸發事件,一共有三種事件:INSERT、UPDATE 或者 DELETE
  • tbname:這個參數指的是觸發器創建的表名,在哪個表上創建
  • triggerstmt: 觸發器的程式體,也就是 SQL 語句

所以,可以創建六種觸發器

BEFORE INSERT、AFTER INSERT、BEFORE UPDATE、AFTER UPDATE、BEFORE DELETE、AFTER DELETE

上面的 for each now 表示任何一條記錄上的操作都會觸發觸發器。

下面我們通過一個例子來演示一下觸發器的操作

我們還是用上面的 procuct 表做例子,我們創建一個 product_info 產品資訊表。

create table product_info(p_info varchar(20)); 

然後我們創建一個 trigger

我們在 product 表中插入一條數據

insert into product values(4,"pineapple",15.3);

我們進行 select 查詢,可以看到現在 product 表中有四條數據

我們沒有向 product_info 表中插入數據,現在我們來看一下 product_info 表中,我們預想到是有數據的,具體來看下

這條數據是什麼時候插入的呢?我們在創建觸發器 tg_pinfo 的時候插入了的這條數據。

刪除觸發器

觸發器可以使用 drop 進行刪除,具體刪除語法如下

drop trigger tg_pinfo;

和刪除表的語法是一樣的

查看觸發器

我們經常會查看觸發器,可以通過執行 show triggers 命令查看觸發器的狀態、語法等資訊。

另一種查詢方式是查詢表中的 information_schema.triggers 表,這個可以查詢指定觸發器的指定資訊,操作起來方便很多

觸發器的作用

  • 在添加一條數據前,檢查數據是否合理,例如檢查郵件格式是否正確
  • 刪除數據後,相當於數據備份的作用
  • 可以記錄資料庫的操作日誌,也可以作為表的執行軌跡

注意:觸發器的使用有兩個限制

  1. 觸發程式不能調用將數據返回客戶端的存儲程式。也不能使用 CALL 語句的動態 SQL 語句。
  2. 不能在觸發器中開始和結束語句,例如 START TRANSACTION