視圖: 視圖是一個虛擬表(非真實存在),動態獲取數據,僅僅能作查詢操做html
本質:【根據SQL語句獲取動態的數據集,併爲其命名】,用戶使用時只需使用【名稱】便可獲取結果集,並能夠將其看成表來使用。因爲視圖是虛擬表,因此沒法使用其對真實表進行建立、更新和刪除操做,PyMysql是支持視圖的。sql
僅能作查詢用。數據庫
建立視圖: create VIEW stu as select * from student; # 這裏只是創建了一個對應關係,視圖是虛表,動態獲取數據 select * from stu; # 這裏只是簡化了操做,實際上仍是執行了select * from student 查看視圖: show TABLES # 會顯示table和view視圖信息 刪除視圖: drop VIEW stu; 修改視圖: ALTER VIEW stu as select * from student where gender = '男'; PyMysql是支持視圖的
對某個表進行【增/刪/改】操做的先後若是但願觸發某個特定的行爲時,可使用觸發器函數
觸發器用於定製用戶對錶的行進行【增/刪/改】先後的行爲性能
觸發器沒法由用戶直接調用,而知因爲對錶的【增/刪/改】操做被動引起的。學習
特別的:優化
NEW表示即將插入的數據行,OLD表示即將刪除的數據行spa
多行操做的時候,每一行都會進行一個輪詢操做code
觸發器的範圍: INSERT、DELETE、UPDATEhtm
觸發器的時機: BEFORE、AFTER
建立觸發器: 特別的:NEW表示即將插入的數據行,OLD表示即將刪除的數據行
CREATE TRIGGER tri_before_insert_tb1 BEFORE INSERT ON student FOR EACH ROW BEGIN IF NEW.gender == 'M' THEN # NEW == student INSERT into Male_stu(sex) VALUES('M'); # 輸入性別爲M,則插入Male_stu ELSE INSERT into Feamle_stu(sex) VALUES('W'); ELSEIF END INSERT into student(gender, class_id, sname) values('W', 1, '哈哈哈') 注意: 更新操做須要2個值,一個NEW傳入的值,一個OLD的值
刪除觸發器
drop TRIGGER tri_before_insert_tb1
存儲過程是一個SQL語句集合[可增刪改查在一個函數裏],當主動去調用存儲過程時,其中內部的SQL語句會按照邏輯執行;內部可又有for等語句。
注意:執行存儲過程,確定會先執行裏面的sql語句的,且只能返回一條結果集,全部有多表的聯合查詢操做是,最好合併爲一條結果集返回。
存儲過程
a. 可寫複雜邏輯
b. 參數:in out inout
c. 結果集:select ...
# 建立無參數的存儲過程,相似函數的建立
CREATE PROCEDURE p1() BEGIN select * from student; END
# 存儲過程調用
call p1() # 使用CALL 存儲名便可, 執行存儲過程,顯示結果
刪除存儲過程:
drop procedure p1;
# 建立有參數的存儲過程,用來執行自定義變量和獲取sql集[結果集只能有一個,但能夠拼接結果集]
# 對於存儲過程,能夠接收參數,其參數有三類:
in 僅用於傳入參數用
out 僅用於返回值用,在內部直接賦值後外部調用能夠直接獲取到內容[Mysql自動幫咱們創建連接關係]
inout 既能夠傳入又能夠看成返回值
create procedure p3(in i1 int,in i2 int,inout i3 int, out r1 int) BEGIN DECLARE temp1 int; # DECLARE聲明變量,且存儲過程裏面必須使用 DECLARE temp2 int default 0; # 聲明默認變量值 set temp1 = 1; set r1 = i1 + i2 + temp1 + temp2; set i3 = i3 + 100; # 功能一:自定義的函數操做 select * from student; # 功能二:查詢並返回結果集,且一次只能返回一個,但能夠拼接結果集 END; # 注意封號是用來執行結果的,沒有封號則不會在執行存儲 -- 執行存儲過程: 使用CALL 存儲名便可 set @t1 =4; # 必須帶@符號 set @t2 = 0; CALL p3 (1, 2 ,@t1, @t2); # 執行存儲,而且自動返回了select * 的結果結合 SELECT @t1,@t2; # 單獨執行此行,僅僅返回了自定義的函數結果
事務用於將某些操做的多個SQL做爲原子性操做,一旦有某一個出現錯誤,便可回滾到原來的狀態,從而保證數據庫數據完整性。
delimiter \ \ create PROCEDURE p1( 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; DELETE from tb1; insert into tb2(name) values('seven'); COMMIT; -- SUCCESS set p_return_code = 0; END\ \ delimiter; 支持事務的存儲過程
函數: 內置函數 + 自定義函數
內置函數:
SELECT 1; select CHAR_LENGTH('hello world'); #11,返回字符長度 SELECT CONCAT('hello ','world ','2017'); # hello world 2017,字符拼接 SELECT CONCAT_WS('_','hello ','world ','2017'); #hello _world _2017,添加了分隔符的字符拼接 SELECT CONV('8', 10, 2); #1000, 進制轉換 10進制轉化2進制 SELECT FORMAT(123456.2,2);#123,456.20 小數點後保留2位 SELECT LOWER('HELLO'); # 大寫變小寫 SELECT UPPER('hello'); # 小寫變大寫 SELECT INSERT('hello',0,2,'YY'); # 不更改,因此說明字符的替換是從第一個位置開始的 SELECT INSERT('hello',1,2,'YY'); # YYllo,從第一個位置開始替換 # 特別的: # 若是pos超過原字符串長度,則返回原字符串 # 若是len超過原字符串長度,則由新字符串徹底替換 SELECT INSTR('hello','e'); # 2, 返回e出現的索引位置 SELECT LEFT('hello', 3); #hel, 獲取前3個字符 SELECT RIGHT('hello',3); #llo, 從右邊取出3個值 SELECT SUBSTRING('hello',1,3); #hel, 默認從第一個位置開始取 SELECT TRIM(' ' ' hello ')# hello, 移除左右的空格 SELECT LTRIM(' hello world '); #helloworld,其引導空格字符被刪除。 SELECT RTRIM(' hello world'); #hello world,結尾空格字符被刪去 SELECT LOCATE('ll','hello'); # 3, 返回字符串所在的位置 SELECT REPEAT('h',5) #hhhhh, 重複前面的字符n次 SELECT REPLACE('hello','ll','yy')#heyyo, 替換字符 SELECT REVERSE('hello') #olleh, 字符反轉 SELECT SPACE(2)# 返回2個空格
自定義函數:函數僅僅支持傳遞參數,返回一個結果,不容許寫sql,不支持返回結果集
建立函數: create function f1(i1 int,i2 int) # 傳遞2個參數 returns int # 返回結果,相似Java publist int f1(int i1, int i2) BEGIN # 函數內容,函數內容不容許寫sql, 不容許獲取結果集 declare num int; set num = i1 + i2; # declare a int; # 函數裏利用 select into 也能夠實現賦值的操做 # select nid into a from student where name = 'hhh'; # 將nid值賦給a return(num); # 返回結果 END; 執行函數: SELECT f1(2,3) # 5 刪除函數: drop function f1;
函數和存儲過程的區別:
相對比較準確表達出當前SQL運行情況,根據參考信息能夠進行SQL優化通常顯示All/Index的時候,效率不高,由於All 是全數據表掃描,index是全索引表掃描,並且rows裏面的數據都是相對的,不是很準確。
- limit 的好處,找到第一個後就不在繼續查找,效率相比較高
select * from tb1 where email='123' -->[不推薦]
select * from tb1 where email='123' limit 1; -->[推薦]
EXPLAIN select sid from student;
EXPLAIN select sid from student;
EXPLAIN select sid from student limit 1; # 也是從表掃描,可是找到第一條後,後面就不執行了
EXPLAIN select sid from student where sid < 12;[因此建立表的時候,能夠考慮將列設置爲索引]
- 對須要進行範圍查找的列進行索引設置,由於在查找 <, <= 等進行操做的時候,使用的是Range範圍查找,可是對於>, !=進行操做的時候,又是全局查找了
- 對於全表查找,最好加上limit, 由於有了limit查找到了數據後,就不在繼續向下查找了
- 查詢時的訪問方式,性能:all < index < range < index_merge < ref_or_null < ref < eq_ref < system / const
- 避免使用select *
- count(1)或count(列) 代替 count(*)
- 建立表時儘可能時 char 代替 varchar[char:定長用於固定長度的表單提交數據存儲效率高, varchar:不定長,效率偏低]
- 表的字段順序固定長度的字段優先[varchar, text是不定長]
- 組合索引代替多個單列索引(常常使用多個條件查詢時,組合索引比單獨索引的合併快)
- 儘可能使用短索引[指定列的某幾個字符爲索引]
- 使用鏈接(JOIN)來代替子查詢(Sub-Queries)
- 連表時注意條件類型需一致
- 索引散列值(重複少)不適合建索引,例:性別不適合
【更多參考】http://www.cnblogs.com/wupeiqi/articles/5713323.html -->視圖
【更多參考】http://www.cnblogs.com/wupeiqi/articles/5716963.html -->索引
【更多參考】http://www.cnblogs.com/wupeiqi/articles/5716963.html -->索引補充