1. 視圖
什么是視圖?
一個查詢語句的結果是一張虛擬表,將這種虛擬表保存下來
它就變成了一個視圖
一個查詢語句的結果是一張虛擬表,將這種虛擬表保存下來
它就變成了一個視圖
為什么要用視圖?
當頻繁需要用到多張表的連表結果,你就可以事先生成好視圖
之后直接調用即可,避免了反復寫連表操作的 sql 語句
當頻繁需要用到多張表的連表結果,你就可以事先生成好視圖
之后直接調用即可,避免了反復寫連表操作的 sql 語句
創建視圖表語法:
create view teacher_course as select * from teacher INNER JOIN course
on teacher.tid = course.teacher_id;
1. 視圖只有表結構,沒有表數據文件;視圖中的數據還是來源於原來的表
2. 不要改動視圖表中的數據
3. 一般情況下不會頻繁的使用視圖來寫業務邏輯
2. 觸發器
概念:在滿足對某張表數據的
增、刪、改 的情況下,
自動觸發 的功能稱之為觸發器
為什么使用???
觸發器專門針對我們對某一張表數據增 insert、刪 delete、改 update 的行為,這類行為一旦執行
就會觸發觸發器的執行,即自動運行另外一段 sql 代碼
就會觸發觸發器的執行,即自動運行另外一段 sql 代碼
創建觸發器語法:
觸發器分為六種情況 >>> (
增前、增后 改前、改后 刪前、刪后)
但語法固定,如下:
create trigger 觸發器名 after / before 增刪改操作(insert / update / delete) on 表名 for each row
begin
sql 語句
end
ps:觸發器名有一定的規律,要做到見名知意;如:
tri_before _insert_t1 >>> 表示在插入表1數據之前的觸發器
tri_after_insert_t1 >>> 表示在插入表1數據之后的觸發器
tri_before_update_t1 >>> 表示在修改表1數據之前的觸發器
tri_after_update_t1 >>> 表示在修改表1數據之后的觸發器
tri_before_delete_t1 >>> 表示在刪除表1數據之前的觸發器
tri_before_delete_t1 >>> 表示在刪除表1數據之后的觸發器
例子用法:
# 創建表
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') # no代表執行失敗 ); CREATE TABLE errlog ( id INT PRIMARY KEY auto_increment, err_cmd CHAR (64), err_time datetime );
# 創建觸發器
補充:NEW對象指代的就是當前記錄 delimiter $$ # 將mysql默認的結束符由;換成$$(因為你的sql語句中可能有多個 ; ,而原本的操作是只要遇到一個 ; 就結束了)
# 只對當前窗口有效 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 ; # 結束之后記得再改回來,不然后面結束符就都是$$了
# 刪除觸發器
drop trigger tri_after_insert_cmd;
3. 事務
事務包含一大堆 sql 語句,這些 sql 要么同時成功,要么一個也別想成功
作用:保證了對數據操作的數據安全性
特性:事務應該具有4個屬性,這四個屬性通常稱為 ACID 特性
原子性(atomicity):
一個事務是一個不可分割的工作單位,事務中包括的諸操作要么都做,要么都不做。
一致性(consistency):
事務必須是使數據庫從一個一致性狀態變到另一個一致性狀態。
一致性與原子性是密切相關的。
隔離性(isolation):
一個事務的執行不能被其他事務干擾。
即一個事務內部的操作及使用的數據對並發的其他事務是隔離的,並發執行的
各個事務之間不能互相干擾。
持久性(durability):
持久性也稱永久性(permanence),指一個事務一旦提交,它對數據庫中數據的
改變就應該是永久性的。
接下來的其他操作或故障不應該對其有任何影響。
開啟事務:start transaction
事務回滾:rollback
永久更改:commit
例子用法:
# 修改數據之前先開啟事務操作 start transaction; # 修改操作 update user set balance=900 where name='wsb'; #買支付100元 update user set balance=1010 where name='egon'; #中介拿走10元 update user set balance=1090 where name='ysb'; #賣家拿到90元 # 回滾到上一個狀態 rollback; # 開啟事務之后,只要沒有執行commit操作,數據其實都沒有真正刷新到硬盤
"""開啟事務檢測操作是否完整,不完整主動回滾到上一個狀態,如果完整就應該執行commit操作""" try: update user set balance=900 where name='wsb'; #買支付100元 update user set balance=1010 where name='egon'; #中介拿走10元 update user set balance=1090 where name='ysb'; #賣家拿到90元 except 異常: # 異常如何檢測?????---> 下面的存儲過程 rollback; else: commit;
4. 存儲過程
存儲過程包含了一系列可執行的 sql 語句,存儲過程存放於 MySQL 中,通過調用它的名字可以執行其內部的一堆 sql
如何創建存儲過程??
# 語法 delimiter $$ create procedure 過程名( in m int, # in表示這個參數只能是傳入,不能被返回 in n int, out res int # out表示這個參數可以被返回出去 inout res int # inout表示這個參數既可以傳入,也可以被返回出去 一般不使用 ) # 關鍵字in/out/inout 值 類型 begin select 字段名 from 表名 where 條件; # 如:select tname from teacher where tid > m and tid < n; set res = 0 # 修改可以返回出去的值,再進行查看,就可以知道有沒有存儲成功 end $$ delimiter ;
如何使用??
# 大前提:存儲過程是在哪個庫下面創建的,就只能在對應的庫下面使用! # 使用一:直接在mysql中調用 set @res = 10 # res的值是用來判斷存儲過程是否被執行成功的依據 # 所以需要先定義一個變量@res存儲10 call p1(2,4,10) # 報錯 call p1(2,4,@res) #使用 call + 過程名字(參數) 來調用存儲過程 # 查看結果 select @res; # @res發生了變化,則表示存儲過程執行成功 # 使用二:在python程序中調用 # pymysql連接mysql # 產生的游標 cursor.callproc('p1',(2,4,10))
# 內部的原理:@_p1_0 = 2 @_p1_1 = 4 @_p1_2 = 10; # 0、1、2對應的為括號內第二個參數索引位置 cursor.execute('select @_p1_2;') # 查看是否有變化
5. 函數
mysql 內置的函數只能在 sql 語句中使用!
參考博客:<http://www.cnblogs.com/linhaifeng/articles/7495918.html#_label2>
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) from blog group by date_format(sub_time,'%Y-%m');
6.流程控制
# if條件語句 delimiter // CREATE PROCEDURE proc_if () # 關鍵詞 procedure 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
* unique key
* index key
* unique key
* index key
注意:
foreign key 不是用來加速查詢用的,不在我們研究范圍之內,
上面三種 key 前兩種除了有加速查詢的效果之外還有額外的約束條件:
(primary key:非空且唯一,unique key:唯一),而index key沒有任何約束功能只會幫你加速查詢
索引就是一種數據結構,類似於書的目錄。意味着以后再查數據應該先找目錄再找數據,而不是用翻頁的方式查詢數據
**本質都是:通過不斷地縮小想要獲取數據的范圍來篩選出最終想要的結果,同時把隨機的事件變成順序的事件
也就是說,有了這種索引機制,我們可以總是用同一種查找方式來鎖定數據。
**索引的影響:
* 在表中有大量數據的前提下,創建索引速度會很慢
* 在索引創建完畢后,對表的查詢性能會大幅度提升
* 在索引創建完畢后,對表的查詢性能會大幅度提升
#### b+樹 <https://images2017.cnblogs.com/blog/1036857/201709/1036857-20170912011123500-158121126.png> 只有葉子結點存放真實數據,根和樹枝節點存的僅僅是虛擬數據 查詢次數由樹的層級決定,層級越低次數越少 一個磁盤塊兒的大小是一定的,那也就意味着能存的數據量是一定的。如何保證樹的層級最低呢?一個磁盤塊兒存放占用空間比較小的數據項 思考我們應該給我們一張表里面的什么字段字段建立索引能夠降低樹的層級高度>>> 主鍵id字段
#### **聚集索引(primary key)** 聚集索引其實指的就是表的主鍵,innodb引擎規定一張表中必須要有主鍵。先來回顧一下存儲引擎。 myisam在建表的時候對應到硬盤有幾個文件(三個)? innodb在建表的時候對應到硬盤有幾個文件(兩個)?frm文件只存放表結構,不可能放索引,也就意味着innodb的索引跟數據都放在idb表數據文件中。 **特點:**葉子結點放的一條條完整的記錄
#### 輔助索引(unique,index) 輔助索引:查詢數據的時候不可能都是用id作為篩選條件,也可能會用name,password等字段信息,那么這個時候就無法利用到聚集索引的加速查詢效果。就需要給其他字段建立索引,這些索引就叫輔助索引 **特點:**葉子結點存放的是輔助索引字段對應的那條記錄的主鍵的值(比如:按照name字段創建索引,那么葉子節點存放的是:{name對應的值:name所在的那條記錄的主鍵值})
select name from user where name='jason';
上述語句叫覆蓋索引:只在輔助索引的葉子節點中就已經找到了所有我們想要的數據
select age from user where name='jason'; 上述語句叫非覆蓋索引,雖然查詢的時候命中了索引字段name,但是要查的是age字段,所以還需要利用主鍵才去查找