Mysql學習---視圖/觸發器/存儲過程/函數/執行計劃/sql優化 180101

視圖

視圖: 視圖是一個虛擬表(非真實存在),動態獲取數據,僅僅能作查詢操做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是支持視圖的

image

觸發器

對某個表進行【增/刪/改】操做的先後若是但願觸發某個特定的行爲時,可使用觸發器函數

觸發器用於定製用戶對錶的行進行【增/刪/改】先後的行爲性能

觸發器沒法由用戶直接調用,而知因爲對錶的【增/刪/改】操做被動引起的。學習

特別的:優化

       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的值

image

刪除觸發器

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;                  # 單獨執行此行,僅僅返回了自定義的函數結果

image

 Mysql學習---使用Python執行存儲過程

事務:Innodb支持事務

事務用於將某些操做的多個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;

函數和存儲過程的區別:

image

 

執行計劃

      相對比較準確表達出當前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;[因此建立表的時候,能夠考慮將列設置爲索引] 

 

對SQL進行優化

- 對須要進行範圍查找的列進行索引設置,由於在查找 <, <= 等進行操做的時候,使用的是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   -->索引補充

相關文章
相關標籤/搜索