1、視圖python
1、什麼是視圖mysql
虛擬表:在硬盤中沒有的,經過查詢在內存中拼接的表web
視圖:經過查詢獲得一張虛擬表,保存下來,下次可直接使用sql
2、爲何要用視圖數據庫
若是要頻繁使用一張虛擬表,能夠不用重複查詢網絡
3、如何用視圖數據結構
create view teacher2course as select * from teacher inner join course on teacher.tid = course.teacher_id;框架
4、刪除視圖ide
drop view teacher2course;函數
5、強調
1、在硬盤中,視圖只有表結構文件(.frm),沒有表數據文件(.idb); 其在後臺對應的是一條sql語句
2、視圖一般是用於查詢,儘可能不要修改視圖中的數據
2、觸發器
1、觸發器:在知足對某張表數據的增、刪、改的狀況下,自動觸發的功能稱之爲觸發器
2、爲什麼要用觸發器?
觸發器專門針對咱們對某一張表數據增insert、刪delete、改update的行爲,這類行爲一旦執行就會觸發觸發器的執行,即自動運行另一段sql代碼
3、建立觸發器語法
# 針對插入
create trigger tri_after_insert_t1 after insert on 表名 for each row #after
begin #begin end 在sql中用於標誌同一執行級別的代碼;至關於python中的縮進
sql代碼。。。
end
create trigger tri_before_insert_t2 before insert on 表名 for each row #before
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
#刪除觸發器
drop trigger tri_after_insert_cmd;
4、案例
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 $$ #修改sql中的默認分隔符,從;改爲$$
create trigger tri_after_insert_cmd after insert on cmd for each row #觸發器名稱要儘量詳細如例
begin
if NEW.success = 'no' then # NEW爲mysql對新插入記錄的封裝名; 若是不用mysql的觸發器,能夠在本身的應用程序中加if判斷
insert into errlog(err_cmd,err_time) values(NEW.cmd,NEW.sub_time);
end if; # mysql中固定用法
end $$ # $$表一行語句終結
delimiter ; # 將sql中的默認分隔符改回;
3、事務(重要)
1、什麼是事務
開啓一個事務能夠包含一些sql語句,這些sql語句要麼同時成功;要麼一個都別想成功,稱之爲事務的原子性
2、事務的做用:轉帳等,屏蔽因網絡傳輸部分失效而帶來的影響
3、如何用 (如下爲運行邏輯,非代碼)
create table user(
id int primary key auto_increment,
name char(32),
balance int
);
insert into user(name,balance)
values
('wsb',1000),
('egon',1000),
('ysb',1000);
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; #若是異常,回滾到前一個狀態,即balance都爲1000
else:
commit; #若是無異常,修改數據庫(硬盤上的數據)
4、存儲過程(重要)
#在mysql中函數是不能單獨使用的,必須放在sql語句中使用;但存儲過程是能夠單獨使用的
1、存儲過程:存儲過程包含了一系列可執行的sql語句,存儲過程存放於MySQL中,經過調用它的名字能夠執行其內部的一堆sql
2、三種開發模型
a、(若是不考慮非技術因素,各方面效率最高的選擇;但考慮到實際狀況,通常不被選擇)
應用程序:只須要開發應用程序的邏輯
mysql:編寫好存儲過程,以供應用程序調用
優勢:開發效率,執行效率都高
缺點:考慮到人爲因素、跨部門溝通等問題,會致使擴展性差
b、(與c的思路一致,會被使用)
應用程序:除了開發應用程序的邏輯,還須要編寫原生sql
mysql:
優勢:比方式1,擴展性高(非技術性的)
缺點:
1、開發效率,執行效率都不如方式1
2、編寫原生sql太過於複雜,並且須要考慮到sql語句的優化問題
c、(考慮到非技術因素,最多見的選擇)
應用程序:開發應用程序的邏輯,不須要編寫原生sql,基於別人編寫好的框架來處理數據,ORM(object relationship matching)
mysql:
優勢:不用再編寫純生sql,這意味着開發效率比方式2高,同時兼容方式2擴展性高的好處
缺點:執行效率連方式2都比不過
3、建立存儲過程
delimiter $$
create procedure p1( #建立存儲過程p1
in m int, #mysql中參數必須先規定類型和用途(in,out,inout)
in n int,
out res int #res用於接收返回值
)
begin
select tname from teacher where tid > m and tid < n;
set res=0;
end $$
delimiter ;
4、如何用存儲過程
a、直接在mysql中調用
set @res=10 #mysql中變量的定義要用@abc的形式
call p1(2,4,@res);
select @res; #查看結果
b、在python程序中調用
import pymysql
conn=pymysql.connect(
host='127.0.0.1',
port=3306,
user='root',
password='123',
charset='utf8',
database='db42'
)
cursor=conn.cursor(pymysql.cursors.DictCursor)
cursor.callproc('p1',(2,4,10)) #@_p1_0=2,@_p1_1=4,@_p1_2=10 #pymysql幫助對傳入變量進行以上變形
print(cursor.fetchall())
cursor.execute('select @_p1_2;') #查看返回值,確認執行結果
print(cursor.fetchone())
cursor.close()
conn.close()
5、事務的使用 (事務+存儲過程)
delimiter //
create PROCEDURE p5(
OUT p_return_code tinyint
)
BEGIN
DECLARE exit handler for sqlexception #若是出現錯誤,執行
BEGIN
-- ERROR
set p_return_code = 1;
rollback;
END;
DECLARE exit handler for sqlwarning #若是出現警告,執行
BEGIN
-- WARNING
set p_return_code = 2;
rollback;
END;
START TRANSACTION; #事務的應用
update user set balance=900 where id =1;
update user123 set balance=1010 where id = 2;
update user set balance=1090 where id =3;
COMMIT;
-- SUCCESS
set p_return_code = 0; #0表明執行成功
END //
delimiter ;
#在python中調用存儲過程
import pymysql
conn=pymysql.connect(
host='127.0.0.1',
port=3306,
user='root',
password='123',
charset='utf8',
database='db44'
)
cursor=conn.cursor(pymysql.cursors.DictCursor)
cursor.callproc('p6',(100,)) #@_p5_0 = 100
cursor.execute('select @_p6_0')
print(cursor.fetchone())
cursor.close()
conn.close()
5、函數
1、強調:mysql內置的函數只能在sql語句中使用
mysql> select date_format(sub_time,'%Y-%m'),count(id) from blog group by date_format(sub_time,'%Y-%m');
2、補充
a、select * from s1 \G #表字段太多(字段行顯示不全)時,用\G將表豎着顯示出來: row1 哪些字段: 對應的內容,row2。。。
b、視圖、觸發器、事務、存儲過程、函數、流程控制皆是在庫下面創建
6、流程控制 (if,while,case)
#case
select
case
when name = 'egon' then
name
when name = 'alex' then
concat(name,'_BIGSB')
else
concat(name,'_SB')
end
from emp;
7、索引
1、爲何要用索引
對於一個應用來講,對數據庫的讀寫比例基本上是10:1,即讀多寫少
並且對於寫來講極少出現性能問題,大多數性能問題都是慢查詢
提到加速查,就必須用到索引
2、什麼是索引
索引就至關於書的目錄,是mysql中一種專門的數據結構,稱爲key(primary key,unique,index key)
索引的本質原理就是經過不斷地縮小查詢範圍,來下降io次數從而提高查詢性能
強調:一旦爲表建立了索引,之後的查詢都會先查索引,再根據索引定位的結果去找數據(同一種方式)
3、索引的影響(先有數據,後有索引;索引,亦佔硬盤空間)
a、在表中有大量數據的前提下,建立索引速度會很慢
b、在索引建立完畢後,對錶的查詢性能會大幅度提高,可是寫性能會下降
4、B+樹:只有葉子節點才存放真實數據,其餘的(根節點、枝節點)都是虛擬數據
a、一次IO走一個block塊
b、淺藍-block塊; 深藍-數據項; 黃-指針
c、爲下降IO次數-》下降樹的高度-》數據項越小越好(block塊大小必定的狀況下,數據項越小,存放的數據量最多)-》採用佔空間少的作索引(好比id)
5、索引的最左匹配特性(從左到右一次匹配)
6、彙集索引(primary key): 組織數據時就按照此索引組織
特色:葉子節點存放的一整條數據
7、輔助索引(unique,index)
特色:若是是按照這個字段建立的索引,那麼葉子節點存放的是:{名字:名字所在那條記錄的主鍵的值}
innodb的索引存放在表數據裏(.idb)
a、覆蓋索引:只在輔助索引的葉子節點中就已經找到了全部咱們想要的數據
select name from user where name='egon';
b、回表操做
select age from user where name='egon';
8、補充: 權限管理
a、受權
grant all on *.* to 'egon' @'192.168.12.%' identified by '123'; #all指的是除了grant之外的所有權限
flush privileges;
exist
b、刪除權限
revoke select on db1.* from 'egon'@'%';
9、其餘:
a、對區別度低的數據不要建索引,且索引不是越多越好
b、注意範圍問題,或者說條件不明確的問題 (條件中出現這些符號或關鍵字:>、>=、<、<=、!= 、between...and...、like)
c、mysql中對 a and b and c。。的形式,會先從有索引或區分度高的數據入手開始查詢,以減小查詢範圍
d、mysql中對 a or b or c。。的形式,會從左至右依次查詢
e、索引列不要參與計算,若是非要運算 a\12=3 ===> a=3\12
f、聯合索引的原則:
區別度高、範圍小的放左邊,區別度低、範圍大的放右邊
(email, name, gender, id):能夠搜(email)、(email,name, gender)等(含email),不能搜(id)等