視圖、觸發器、事務、存儲過程、函數、流程控制、索引與慢查詢優化

視圖、觸發器、事務、存儲過程、函數、流程控制、索引與慢查詢優化

1、視圖

一、什麼是視圖

視圖就是將SQL語句的查詢結果獲得的一張虛擬表,保存下來僅保留表結構,這張虛擬表就是視圖python

二、爲何要用視圖

爲了便於後期直接查詢,節省拼接表的時間消耗mysql

三、怎麼用視圖

語法:create view 視圖名 as sql語句sql

create view class_student as select * from class inner join student on class.cid = student.class_id;

注意:一、建立出來的視圖只有表結構,沒有表數據,數據仍是源於原來的表數據庫

​ 二、不要修改視圖中的數據,會直接影響原表中的數據,視圖只用於查詢安全

通常開發工做中,不用視圖,由於後期想拓展功能,會須要對視圖進行修改,意味着你須要先在mysql視圖修改而後再去程序中修改,須要跨部門溝通,全部通常不用視圖數據結構

2、觸發器

一、什麼是觸發器

在對某張表的數據進行增、刪、改的一些操做下,自動觸發的,稱之爲觸發器函數

二、爲何要用觸發器

在對一張表數據進行增insert、刪delete、改update時,一旦有這種行爲,就會觸發觸發器去執行一段SQL代碼優化

能夠對增/刪/改,前/後 觸發觸發器ui

完整語法:create trigger 觸發器名字 before/after insert/delete/update for each  row
begin
	sql語句...
end

注意:觸發器名字,命名規範最好使用下劃線體,而且見名知意,如:tri_before_insert_t1日誌

delimiter $$ # 將mysql默認的結束符由;換成$$

# 針對插入
create trigger tri_after_insert_t1 after insert on 表名 for each row
begin
    sql代碼。。。
end 
create trigger tri_before_insert_t2 before insert on 表名 for each row
begin
    sql代碼。。。
end

# 針對刪除
create trigger tri_after_delete_t1 after delete on 表名 for each row
begin
    sql代碼。。。
end
create trigger tri_before_delete_t2 before delete on 表名 for each row
begin
    sql代碼。。。
end

# 針對修改
create trigger tri_after_update_t1 after update on 表名 for each row
begin
    sql代碼。。。
end
create trigger tri_before_update_t2 before update on 表名 for each row
begin
    sql代碼。。。
end

# 案例
CREATE TABLE cmd (
    id INT PRIMARY KEY auto_increment,
    USER CHAR (32),
    priv CHAR (10),
    cmd CHAR (64),
    sub_time datetime, #提交時間
    success enum ('yes', 'no') #0表明執行失敗
);

CREATE TABLE errlog (
    id INT PRIMARY KEY auto_increment,
    err_cmd CHAR (64),
    err_time datetime
);

delimiter $$  # 將mysql默認的結束符由;換成$$
create trigger tri_after_insert_cmd after insert on cmd for each row
begin
    if NEW.success = 'no' then  # 新記錄都會被MySQL封裝成NEW對象
        insert into errlog(err_cmd,err_time) values(NEW.cmd,NEW.sub_time);
    end if;
end $$
delimiter ;  # 結束以後記得再改回來,否則後面結束符就都是$$了

#往表cmd中插入記錄,觸發觸發器,根據IF的條件決定是否插入錯誤日誌
INSERT INTO cmd (
    USER,
    priv,
    cmd,
    sub_time,
    success
)
VALUES
    ('egon','0755','ls -l /etc',NOW(),'yes'),
    ('egon','0755','cat /etc/passwd',NOW(),'no'),
    ('egon','0755','useradd xxx',NOW(),'no'),
    ('egon','0755','ps aux',NOW(),'yes');

# 查詢errlog表記錄
select * from errlog;
# 刪除觸發器
drop trigger tri_after_insert_cmd;

3、事務

一、什麼是事務

開啓一個事務能夠包含一些SQL語句,這些SQL語句要麼同時成功要麼同時失敗,保證數據操做的安全性一致性,稱爲事務的原子性

二、爲何要用事務

保證了對數據操做的安全性

三、事務的四大特性ACID

原子性:一個事務中包含的各類對數據的操做,要麼操做都成功,要麼都失敗

一致性:一致性和原子性是密切相關的,事務使數據庫從一個一致性的狀態變爲另外一個一致性狀態

隔離性:事務內的操做數據與另外一個事務內的操做數據是隔離的,互不干擾的

持久性(永久性):事務一旦提交就會發生永久性改變

四、怎麼使用事務

# 修改數據以前先開啓事務操做
start transaction;

# 修改操做
update user set balance=20000000 where name='Mr沈'; 

# 回滾到上一個狀態
rollback;

# 開啓事務以後,只要沒有執行commit操做,數據其實都沒有真正刷新到硬盤
# 提交操做
commit;
"""開啓事務檢測操做是否完整,不完整主動回滾到上一個狀態,若是完整就應該執行commit操做"""

4、存儲過程

至關於自定義的函數:

​ 內部封裝了一系列的SQL語句,讓不會mysql操做的的也能夠經過調用該存儲過程來操做數據庫,或者爲了方便調用

語法:

# 有參
delimiter$$
create procedure p1(
    in m int,  # in表示這個參數必須只能是傳入不能被返回出去
    in n int,  
    out res int  # out表示這個參數能夠被返回出去,還有一個inout表示便可以傳入也能夠被返回出去
)
begin
    select tname from teacher where tid > m and tid < n;
    set res=0;
end$$
delimiter;
# 無參
delimiter $$
create procedure p1()
begin
	select * from user;
end $$
delimiter;

如何使用:

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

# 查看結果
select @res;  # 執行成功,@res變量值發生了變化

# 二、在python程序中調用
pymysql連接mysql
產生的遊表cursor.callproc('p1',(2,4,10))  # 內部原理:@_p1_0=2,@_p1_1=4,@_p1_2=10;
cursor.excute('select @_p1_2;')

5、函數

注意與存儲過程的區別,mysql內置的函數只能SQL語句中使用

CREATE TABLE blog (
    id INT PRIMARY KEY auto_increment,
    NAME CHAR (32),
    sub_time datetime
);

INSERT INTO blog (NAME, sub_time)
VALUES
    ('第1篇','2015-03-01 11:31:21'),
    ('第2篇','2015-03-11 16:31:21'),
    ('第3篇','2016-07-01 10:21:31'),
    ('第4篇','2016-07-22 09:23:21'),
    ('第5篇','2016-07-23 10:11:11');

select date_format(sub_time,'%Y-%m'),count(id) from blog group by date_format(sub_time,'%Y-%m');

6、流程控制

# if條件語句
delimiter //
CREATE PROCEDURE proc_if ()
BEGIN
    declare i int default 0;
    if i = 1 THEN
        SELECT 1;
    ELSEIF i = 2 THEN
        SELECT 2;
    ELSE
        SELECT 7;
    END IF;

END //
delimiter ;
# while循環
delimiter //
CREATE PROCEDURE proc_while ()
BEGIN
    DECLARE num INT ;
    SET num = 0 ;
    WHILE num < 10 DO
        SELECT
            num ;
        SET num = num + 1 ;
    END WHILE ;
END //
delimiter ;

7、索引與慢查詢優化

數據都是存在硬盤上,查詢數據就須要進行IO操做

索引在mysql中也叫,是儲存引擎用於快速找到記錄的一種數據結構,相似於書的目錄

索引有三種:

  • primary key
  • uinque key
  • index key

注意:foreign key不是用來加速查詢用的,不在咱們研究範圍以內,上面三種key前兩種除了有加速查詢的效果以外還有額外的約束條件(primary key:非空且惟一,unique key:惟一),而index key沒有任何約束功能只會幫你加速查詢

本質都是:經過不斷地縮小想要獲取數據的範圍來篩選出最終想要的結果,同時把隨機的事件變成順序的事件,也就是說,有了這種索引機制,咱們能夠老是用同一種查找方式來鎖定數據。

b+樹

只有葉子結點存放真實數據,根和樹枝節點存的僅僅是虛擬數據

查詢次數由樹的層級決定,層級越低次數越少

一個磁盤塊兒的大小是必定的,那也就意味着能存的數據量是必定的。如何保證樹的層級最低呢?

  • 索引字段要儘可能的小
  • 索引的最左匹配特性

彙集索引:指的就是表的主鍵,innodb引擎規定一張表中必需要有主鍵

輔助索引:查詢數據的時候不可能都是用id做爲篩選條件,也可能會用name,password等字段信息,那麼這個時候就沒法利用到彙集索引的加速查詢效果。就須要給其餘字段創建索引,這些索引就叫輔助索引

select name from user where name='Mr沈';

上述語句叫覆蓋索引:只在輔助索引的葉子節點中就已經找到了全部咱們想要的數據

select age from user where name='Mr沈';

上述語句叫非覆蓋索引,雖然查詢的時候命中了索引字段name,可是要查的是age字段,因此還須要利用主鍵纔去查找

若是name是索引的話,那麼直接用name=‘Mr沈’,這就是命中索引,若是不是直接用name,就是非命中索引

相關文章
相關標籤/搜索