1. 程式人生 > 資料庫 >Mysql系列之六(檢視,事務,觸發器等)

Mysql系列之六(檢視,事務,觸發器等)

檢視

1.什麼是檢視

檢視就是通過查詢一張表儲存起來,下次可以接著用

2.為什麼要用檢視

如果要頻繁的使用一張虛擬表,你可以製作成檢視,後續直接使用

3.如何操作

# 固定語法
create view 視圖表明 as sql語句獲得的虛擬表

具體操作
# 具體操作
create view teacher2course as
select * from teacher INNER JOIN course
on teacher.tid = course.teacher_id
; 

注意

1.檢視建立在硬盤裡只有表結構,資料並沒有寫入硬碟
2.檢視只能用來檢視,如果對檢視的資料進行修改則可能會影響原始表中的資料
3.檢視不方便維護

綜上:檢視很少使用

觸發器

什麼是觸發器

觸發器是指在對資料進行增刪改查操作的基礎上,自動觸發的功能
主要用於:日誌記錄監控等方面
主要有以下的幾種組合
before/after delete/update/insert

觸發器的具體用法

# 固定語法
create trigger 觸發器的名字 before/after delete/update/insert on 表名 for each row
begin
	sql語句
end

# 針對命名
要見名知意,如 tri_bef_del_student

# 增對;問題
由於在定義觸發器的過程中需要用;來明確語意,所以通常在使用前後更改。
方法:
	delimiter \\
	delimiter ;

觸發器的例項式**

# 案例
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
);
"""
當cmd表中的記錄succes欄位是no那麼就觸發觸發器的執行去errlog表中插入資料
NEW指代的就是一條條資料物件
"""
delimiter $$
create trigger tri_after_insert_cmd after insert on cmd 
for each row
begin
	if NEW.success = 'no' then
    	insert into errlog(err_cmd,err_time) values(NEW.cmd,NEW.sub_time);
    end if;
end $$
delimiter ;

# 朝cmd表插入資料
INSERT INTO cmd (
    USER,
    priv,
    cmd,
    sub_time,
    success
)
VALUES
    ('jason','0755','ls -l /etc',NOW(),'yes'),
    ('jason','0755','cat /etc/passwd',NOW(),'no'),
    ('jason','0755','useradd xxx',NOW(),'no'),
    ('jason','0755','ps aux',NOW(),'yes');

# 刪除觸發器
drop trigger tri_aft;

事務(**)

1.什麼是事務

事務是指在資料在多條資料一起操作的過程中,要麼都成功,要麼都失敗

2.事務的四大特性

ACID四大特性
1.原子性
	原子性是指將一個事務作為原子,整體操作,一個失敗則全體失敗
2.一致性
	一致性是指事務從一個狀態到另外一個狀態,與原子性精密相連
3.隔離性
	隔離性是指事務與事務之間不受干擾
4.永續性
	永續性是指事務結束後,資料更改應該是永久性的,而不是短暫的

事務的用法

1.開啟事務
start transaction;
2.回滾操作(回到事務之前的操作)
rollback;
3.確認(確認之後就無法回滾)
commit



"""模擬轉賬功能"""
create table user(
	id int primary key auto_increment,
    name char(16),
    balance int
);
insert into user(name,balance) values
('jason',1000),
('egon',1000),
('tank',1000);


# 1 先開啟事務
start transaction;
# 2 多條sql語句
update user set balance=900 where name='jason';
update user set balance=1010 where name='egon';
update user set balance=1090 where name='tank';

"""
總結
	當你想讓多條sql語句保持一致性 要麼同時成功要麼同時失敗 
	你就應該考慮使用事務
"""

儲存過程

什麼是儲存過程

儲存過程就是講各種執行封裝成函式,以供呼叫

基本使用

定義:
create procedure 名稱(
	in m int  #只接受資料,
	out n int  #輸出資料,
	inout b int  #即輸出有接受
)
begin
	sql程式碼;
end;

呼叫:call p1(引數)

三種開發模式

第一種

"""
應用程式:程式設計師寫程式碼開發
MySQL:提前編寫好儲存過程,供應用程式呼叫

好處:開發效率提升了 執行效率也上去了
缺點:考慮到認為元素、跨部門溝通的問題  後續的儲存過程的擴充套件性差
"""

第二種

'''
應用程式:程式設計師寫程式碼開發之外 設計到資料庫操作也自己動手寫
優點:擴充套件性很高
缺點:
	開發效率降低
	編寫sql語句太過繁瑣 而且後續還需要考慮sql優化的問題
'''

第三種

"""
應用程式:只寫程式程式碼 不寫sql語句 基於別人寫好的操作MySQL的python框架直接呼叫操作即可			ORM框架  
優點:開發效率比上面兩種情況都要高 
缺點:語句的擴充套件性差 可能會出現效率低下的問題 
"""

儲存過程具體演示

delimiter \\
create procedure p1(
	in m int,
	in n int,
	out res int
)
begin
	select * from cmd where id > m and id <n;
	set res = 666;
end \\
delimiter ;

注意:在Mysql客戶端使用的話必須要先定義一個變數res,輸出的時候才能有變數名繫結
定義語法:
set @res = 0;
呼叫語法:
select @res;

在pymysql中如何呼叫儲存過程

import pymysql


conn = pymysql.connect(
    host='127.0.0.1',
    port=3306,
    user='root',
    password='123456',
    database='day49',
)
cursor = conn.cursor(pymysql.cursors.DictCursor)
res = cursor.callproc('p1', (10, 14, 666))
cursor.featchall() # 有返回值	
'''
這裡pymysql模組自動對傳入的值進行了變形操作
@_p1_0
@_p1_1
@_p1_2
'''
cursor.execute('select @_p1_2') 
# [{'@_p1_2': 666}]
print(cursor.fetchall())

函式

函式就是mysql內建的一些功能,通過關鍵字()的方式可以呼叫

NOW()方法
('jason','0755','ls -l /etc',NOW(),'yes')

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'),
    ('第6篇','2016-07-25 11:21:31'),
    ('第7篇','2017-03-01 15:33:21'),
    ('第8篇','2017-03-01 17:32:21'),
    ('第9篇','2017-03-01 18:31:21');

select date_format(sub_time,'%Y-%m'),count(id) fr

流程控制

例如python中的if,while迴圈在mysql中也有固定的語法

# 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 ; 

索引

資料存放在硬碟中,當我們查詢資料時候不得不與硬碟打交道,那麼就必須要進行IO操作。
索引:類似於書的目錄,是一種資料結構,是用來加速資料的查詢的。
索引在MySQL中也叫'鍵',主要有以下三種:
	primary key
	unique key
	index key
注意foreign key不是用來加速查詢用的,不在我們的而研究範圍之內

上面的三種key,前面兩種除了可以增加查詢速度之外各自還具有約束條件,而最後一種index key沒有任何的約束條件,只是用來幫助你快速查詢資料

本質

我們原來查詢資料是一頁一頁的找,沒有目的性,
而索引則形成了一種固定的機制來幫助我們查詢資料。

索引的優缺點

'''
在同一個表中可以有多個不同的索引,但是我們不是每一個欄位都需要加上索引
'''
'''
索引的優缺點:	
	優點:
		· 能夠加速查詢的順序
	缺點:
		· 當列表中已經存在大量資料的情況下,建立索引需要的時間很長
		· 當我們更改資料時,那麼原來的索引失效,所以會在我們更改資料的同時建立索引,使我們對錶修改的速度大大降低
'''

b+樹

b+樹是一種資料查詢機制
通過多分法將資料分為幾個範圍,逐漸縮小查詢,
注意:在體幹上存放的是虛擬資料,只有葉子(最底層存放了真實的資料)

為什麼會將id列通常作為主鍵?
因為id列站硬碟空間小,在同一個block中存放的資料更多,這樣b+樹的層級低,速度更快

在這裡插入圖片描述

聚集索引

聚集索引就是指主鍵
	primary key

輔助索引(unique,index)

查詢資料的時候不可能一直使用主鍵,有時我們需要用其他的列,給其他的列建立索引
'''
注意:
	在輔助索引中存放的是主鍵的id號
	拿到id號後還要在聚合索引中進行查詢
'''

覆蓋索引

'''
是指所查詢的資料就是在索引列,那麼此時會直接返回資料,不要再次查詢(在輔助索引的葉子節點就已經拿到了需要的資料)
'''

# 給name設定輔助索引
select name from user where name='jason';
# 非覆蓋索引
select age from user where name='jason';