1. 程式人生 > 其它 >MySQL補充知識及索引

MySQL補充知識及索引

昨日內容回顧

  • 多表查詢的關鍵字

    inner join...on...

    left join...on....

    right join...on...

  • SQL關鍵字補充

    concat/concat_ws/add/change/modify

  • 多表查詢實操方式

    1. 觀察表的相互聯絡,確定需要操作的表;
    2. 根據目標條件分析操作順序,逐步操作。
  • pymysql模組

    操作步驟:連線服務端→生成遊標→傳送指令→接收結果

    須記憶相關程式碼。

今日內容概要

  • SQL注入問題
  • 檢視
  • 觸發器
  • 儲存過程
  • 流程控制
  • 內建函式
  • 索引與慢查詢優化

今日內容詳細

SQL注入問題

該問題出現的主要原因是在向MySQL服務端傳入資料時,資料本身中含有特殊符號,導致資料本身偏離了起原有的含義,而變成了MySQL中特有的語句。

要解決SQL的注入問題,則需要對傳送的資料進行限制,使傳入的資料不會與SQL語句衝突。

使用pymysql模組傳輸SQL語句時,避免手動拼接資料,而是先使用佔位符佔位,在呼叫execute方法時再傳入相關資料,由execute方法自動對應可避免SQL注入問題。

檢視

當需要多次使用某次資料查詢的結果時,可以將該結果儲存為檢視,之後使用時呼叫該檢視即可。

建立檢視的語句如下

create view 檢視名 as 某次資料查詢的結果;

檢視內的資料無法被更改,僅供檢視及呼叫。

在使用cmd視窗操作MySQL時,儘量不推薦使用檢視,因為建立的檢視會跟原本的資料一同展示在database下,容易造成表的混淆。

在使用視覺化軟體操作MySQL時,檢視會與原資料表分開展示。

觸發器

觸發器(trigger)即滿足一定條件後一段自動觸發的程式碼。MySQL中常見的觸發器一般為修改操作前後。

建立觸發器的語句如下

create trigger 觸發器名 before/after insert/update/delete on 表名 for each row
begin
	sql語句
end

觸發器命名需要遵守一定的規範,即 tri_before_insert_t

觸發器中的SQL語句需要使用分號,因此需要臨時改變SQL語句的結束符。臨時修改結束符使用delimiter關鍵字。

事務

事務的四大特性

mysql中事務是一連串操作的合稱,事務具有四個屬性ACID:

A:Atomicity,原子性,即事務內的操作是不可分割的,所有事務必須同時成功或失敗。

C:Consistency,一致性,即事務的結果必須時資料庫由一個一致性狀態變為另一個一致性狀態。

I:Isolation,隔離性,即不同的事務之間是互不干擾的,即一個事務的執行不會影響另一事務的執行。

D:Duration,永久性,即事務對資料庫造成的影響是永久的,不可逆的。

事務的相關關鍵字

start transaction 開始事務操作。

rollback 返回當前事務操作前的資料庫狀態。

commit 確認事務操作完成,在commit之前,對資料庫的操作都儲存在記憶體中,並未修改硬碟資料。

savepoint 存檔點,規定rollback的節點,事務commit之後存檔點會被刪除。

事務的隔離級別

在InnoDB中事務有四個隔離級別:

read uncommitted(可讀取未提交資料),該隔離級別隔離程度較低,一個事務在執行過程中,另一個事務可呼叫該事務正在操作的資料,造成"髒讀"現象。

read committed(可讀取已提交資料),多數資料庫系統的預設隔離級別,即一個事務在執行過程中資料不可被呼叫,只有執行完成後資料才可被呼叫。

repeatable read(可重複讀取),一個事務在執行過程當中,多次讀取同一資料,而且得到相同的結果,即為可重複讀,這是MySQL預設的隔離級別。若在該事務未操作資料庫的時間內,另一事務對該資料進行了修改,下次讀取時,得到了不同的結果,則出現所謂的"幻讀"。InnoDB通過採取多版本併發控制(MVCC, Multi-verson Concurrency Control)和間隙鎖解決"幻讀"問題。

serializable(可序列讀),即將所有事務必須序列執行,很少使用。

儲存過程

儲存過程(procedure)是封裝的自定義的固定操作,定義procedure與定義trigger相似,區別是需要手動呼叫。

# 無參版本
delimiter $$
create procedure p1()
begin
	select * from cmd;
end $$
delimiter ;

# 呼叫
call p1()


# 有參版本
delimiter $$
create procedure p2(
    in m int,  # in表示這個引數必須只能是傳入不能被返回出去
    in n int,  
    out res int  # out表示這個引數可以被返回出去,還有一個inout表示即可以傳入也可以被返回出去
)
begin
    select * from cmd where id > m and id < n;
    set res=0;  # 用來標誌儲存過程是否執行
end $$
delimiter ;
# 針對res需要先提前定義
set @res=10;  定義
select @res;  檢視
call p1(1,5,@res)  呼叫
select @res  檢視

# 大前提:儲存過程在哪個庫下面建立的只能在對應的庫下面才能使用!!!

# 1、直接在mysql中呼叫
set @res=10  # res的值是用來判斷儲存過程是否被執行成功的依據,所以需要先定義一個變數@res儲存10
call p1(2,4,10);  # 報錯
call p1(2,4,@res);  

# 檢視結果
select @res;  # 執行成功,@res變數值發生了變化

# 2、在python程式中呼叫
pymysql連結mysql
產生的遊標cursor.callproc('p1',(2,4,10))  # 內部原理:@_p1_0=2,@_p1_1=4,@_p1_2=10;
cursor.excute('select @_p1_2;')

流程控制

MySQL中可以實現流程控制,使用方法例:

# 分支結構
DECLARE i int default 0;
IF i = 1 THEN
	SELECT 1;
ELSEIF i = 2 THEN
	SELECT 2;
ELSE
	SELECT 7;
END IF;

# 迴圈結構
DECLARE num int ;
SET num = 0 ;
WHILE num < 10 DO
	SELECT num ;
	SET num = num + 1 ;
END WHILE ;

內建函式

MySQL中內建函式可以通過使用 help 函式名檢視其解釋說明即使用範例。簡單內建函式有:

Trim/Ltrim/Rtrim 移除首尾/左/右指定字元

Upper/Lower 大寫/小寫轉換

Left/Right 獲取從左/右開始指定個數字元

Soundex 查詢發音(英語)相似字元

date_format 識別日期格式

索引與慢查詢優化

索引的相關概念

索引是為了加速對錶中資料行的檢索而建立的一種分散的儲存結構。索引是針對表而建立的,它是由資料頁面以外的索引頁面組成的,每個索引頁面中的行都會含有邏輯指標,以便加速檢索物理資料。

資料庫中索引也稱為鍵,常見的鍵分為3種,主鍵(primary key)、特徵值鍵(unique key)、索引鍵(index key)。

主鍵索引為聚集索引,其餘兩種索引為非聚集索引,非聚集索引實質還是要依賴聚集索引。

索引的優劣勢

優勢:加快資料索引速度。

劣勢:佔用實體記憶體空間,降低資料修改速度。

索引的資料結構

索引底層是樹形結構,樹是計算機底層的資料結構。

常見的樹有二叉樹、b樹、b+樹、b*樹。

二叉樹即每個節點只能向下做兩個分支的樹,b樹即每個節點所能儲存的資料量是固定的。

b+樹與b*樹僅有最下層節點才儲存真正的資料,上層節點僅儲存索引資料。

特點是b+樹在最底層有指向其他同級節點的指標,b*樹在每一級節點都有指向其他同級節點的指標。

慢索引優化

使用explain關鍵字可檢視當前SQL語句的索引速度級別,由慢到快依次為:

1)index 儘量避免
2)range 一般要求
3)ref
4)eq_ref
5)const
6)system
7)null