Day 37 SQL基礎(五)

事務處理

事務用於將某些操做的多個SQL做爲原子性操做,一旦有某一個出現錯誤,便可回滾到原來的狀態,從而保證數據庫數據完整性mysql

開始事務

start transaction程序員

標識事務的開始sql

回滾事務

rollback數據庫

用來回退(撤銷)SQL語句編程

select * from users;
start transaction;
update users set age = 18 where id = 120;
delete from users where name = 'tiny';
rollback;
select * from users;

rollback只能在一個事務處理內使用,在執行一條start transaction命令以後安全

提交事務

commit服務器

通常的MySQL語句都是直接針對數據庫表執行和編寫的.這就是所謂的隱含提交,即提交(寫或保存)操做是自動進行的.網絡

可是.在事務處理塊中,提交不會隱含地進行.爲進行明確的提交,使用commit語句併發

start transaction;
update users set age = 18 where id = 120;
delete from users where name = 'tiny';
commit;

事務的特性

  • 原子性(Atomicity): 原子意爲最小的粒子,即不能再分事務,要麼所有執行,要麼所有取消
  • 一致性(Consistency): 指事務發生前發生後,數據的總額依然匹配
  • 隔離性(Isolation): 簡單點說,某個事務的操做對其餘事務是不可見的
  • 持久性(Durability): 當事務完成後,其影響應該保留下來,不能撤銷,只能經過'補償性事務'來抵消以前的錯誤

存儲引擎

什麼是存儲引擎

MySQL中的數據用各類不一樣的技術存儲在文件(或者內存)中。這些技術中的每一種技術都使用不一樣的存儲機制、索引技巧、鎖定水平而且最終提供普遍的不一樣的功能和能力。經過選擇不一樣的技術,你可以得到額外的速度或者功能,從而改善你的應用的總體功能。

例如,若是你在研究大量的臨時數據,你也許須要使用內存存儲引擎。內存存儲引擎可以在內存中存儲全部的表格數據。又或者,你也許須要一個支持事務處理的數據庫(以確保事務處理不成功時數據的回退能力)。

這些不一樣的技術以及配套的相關功能在MySQL中被稱做存儲引擎(也稱做表類型)。

MySQL默認配置了許多不一樣的存儲引擎,能夠預先設置或者在MySQL服務器中啓用。你能夠選擇適用於服務器、數據庫和表格的存儲引擎,以便在選擇如何存儲你的信息、如何檢索這些信息以及你須要你的數據結合什麼性能和功能的時候爲你提供最大的靈活性。

選擇如何存儲和檢索你的數據的這種靈活性是MySQL爲何如此受歡迎的主要緣由。其它數據庫系統 (包括大多數商業選擇)僅支持一種類型的數據存儲

遺憾的是,其它類型的數據庫解決方案採起的「一個尺碼知足一切需求」的方式意味着你要麼就犧牲一些性能,要麼你就用幾個小時甚至幾天的時間詳細調整你的數據庫。使用MySQL,咱們僅須要修改咱們使用的存儲引擎就能夠了。

mysql5.6支持的存儲引擎包括InnoDB、MyISAM、MEMORY、CSV、BLACKHOLE、FEDERATED、MRG_MYISAM、ARCHIVE、PERFORMANCE_SCHEMA。其中NDB和InnoDB提供事務安全表,其餘存儲引擎都是非事務安全表。

各存儲引擎的特性

概覽

MySQL服務器採用了多層設計和獨立模塊,插件式存儲引擎體系結構,容許將存儲引擎加載到正在運新的MySQL服務器中,圖中的Pluggable Storage Engines部分。採用MySQL服務器體系結構,因爲在存儲級別上(也就是Pluggable Storage Engines)提供了一致和簡單的應用模型和API,應用程序編程人員和DBA可再也不考慮全部的底層實施細節。所以,儘管不一樣的存儲引擎具備不一樣的能力,應用程序是與之分離的。存儲引擎就司職與文件系統打交道了。

各類存儲引擎的特性

  1. 併發性:某些應用程序比其餘應用程序具備不少的顆粒級鎖定要求(如行級鎖定)。
  2. 事務支持:並不是全部的應用程序都須要事務,但對的確須要事務的應用程序來講,有着定義良好的需求,如ACID兼容等。
  3. 引用完整性:經過DDL定義的外鍵,服務器須要強制保持關聯數據庫的引用完整性。
  4. 物理存儲:它包括各類各樣的事項,從表和索引的總的頁大小,到存儲數據所需的格式,到物理磁盤。
  5. 索引支持:不一樣的應用程序傾向於採用不一樣的索引策略,每種存儲引擎一般有本身的編制索引方法,但某些索引方法(如B-tree索引)對幾乎全部的存儲引擎來講是共同的。
  6. 內存高速緩衝:與其餘應用程序相比,不一樣的應用程序對某些內存高速緩衝策略的響應更好,所以,儘管某些內存高速緩衝對全部存儲引擎來講是共同的(如用於用戶鏈接的高速緩衝,MySQL的高速查詢高速緩衝等),其餘高速緩衝策略僅當使用特殊的存儲引擎時才惟必定義。
  7. 性能幫助:包括針對並行操做的多I/O線程,線程併發性,數據庫檢查點,成批插入處理等。
  8. 其餘目標特性:可能包括對地理空間操做的支持,對特定數據處理操做的安全限制等。

各存儲引擎的介紹

InnoDB:MySql 5.6 版本默認的存儲引擎。InnoDB 是一個事務安全的存儲引擎,它具有提交、回滾以及崩潰恢復的功能以保護用戶數據。InnoDB 的行級別鎖定以及 Oracle 風格的一致性無鎖讀提高了它的多用戶併發數以及性能。InnoDB 將用戶數據存儲在彙集索引中以減小基於主鍵的普通查詢所帶來的 I/O 開銷。爲了保證數據的完整性,InnoDB 還支持外鍵約束。

MyISAM:MyISAM既不支持事務、也不支持外鍵、其優點是訪問速度快,可是表級別的鎖定限制了它在讀寫負載方面的性能,所以它常常應用於只讀或者以讀爲主的數據場景。

Memory:在內存中存儲全部數據,應用於對非關鍵數據由快速查找的場景。Memory類型的表訪問數據很是快,由於它的數據是存放在內存中的,而且默認使用HASH索引,可是一旦服務關閉,表中的數據就會丟失

BLACKHOLE:黑洞存儲引擎,相似於 Unix 的 /dev/null,Archive 只接收但卻並不保存數據。對這種引擎的表的查詢經常返回一個空集。這種表能夠應用於 DML 語句須要發送到從服務器,但主服務器並不會保留這種數據的備份的主從配置中。

CSV:它的表真的是以逗號分隔的文本文件。CSV 表容許你以 CSV 格式導入導出數據,以相同的讀和寫的格式和腳本和應用交互數據。因爲 CSV 表沒有索引,你最好是在普通操做中將數據放在 InnoDB 表裏,只有在導入或導出階段使用一下 CSV 表。

NDB:(又名 NDBCLUSTER)——這種集羣數據引擎尤爲適合於須要最高程度的正常運行時間和可用性的應用。注意:NDB 存儲引擎在標準 MySql 5.6 版本里並不被支持。目前可以支持

MySql 集羣的版本有:基於 MySql 5.1 的 MySQL Cluster NDB 7.1;基於 MySql 5.5 的 MySQL Cluster NDB 7.2;基於 MySql 5.6 的 MySQL Cluster NDB 7.3。一樣基於 MySql 5.6 的 MySQL Cluster NDB 7.4 目前正處於研發階段。

Merge:容許 MySql DBA 或開發者將一系列相同的 MyISAM 表進行分組,並把它們做爲一個對象進行引用。適用於超大規模數據場景,如數據倉庫。

Federated:提供了從多個物理機上聯接不一樣的 MySql 服務器來建立一個邏輯數據庫的能力。適用於分佈式或者數據市場的場景。

Example:這種存儲引擎用以保存闡明如何開始寫新的存儲引擎的 MySql 源碼的例子。它主要針對於有興趣的開發人員。這種存儲引擎就是一個啥事也不作的 "存根"。你可使用這種引擎建立表,可是你沒法向其保存任何數據,也沒法從它們檢索任何索引。

視圖

視圖是一個虛擬表(非真實存在),其本質根據SQL語句獲取動態的數據集,併爲其命名,用戶使用時只需使用名稱便可獲取結果集,能夠將該結果集當作表來使用.

使用視圖咱們能夠把查詢過程當中的臨時表摘出來,用視圖去實現,這樣之後再想操做該臨時表的數據是就無需重寫複雜的SQL了,直接去視圖中查找便可,但視圖有明顯的效率問題,而且視圖是放在數據庫中的,若是咱們程序中使用的SQL過度依賴數據庫中的視圖,即強耦合,那就意味着擴展SQL極爲不便,所以並不推薦使用

建立視圖

create view users_view as select * from users;
select * from users_view;

刪除視圖

drop view users_view

修改視圖

alter view user_view as select * from users where id > 1000;

咱們不可以直接修改視圖內是記錄,並且在涉及多個表的狀況下是根本沒法修改視圖中的記錄的,可是當咱們直接修改表內的記錄時,視圖中的記錄也會發生相應的變化

觸發器

觸發器是MySQL響應一下任意語句而自動執行的一條MySQL語句(或位於BEGIN和END語句之間的一組語句):

delete

insert

update

其餘MySQL語句不支持觸發器

建立觸發器

在建立觸發器時,須要給出4條信息

  • 惟一的觸發器名
  • 觸發器關聯的表
  • 觸發器應該響應的活動
  • 觸發器什麼時候執行

觸發器用create trigger語句建立

# 插入前
CREATE TRIGGER tri_before_insert_tb1 BEFORE INSERT ON tb1 FOR EACH ROW
BEGIN
    ...
END

# 插入後
CREATE TRIGGER tri_after_insert_tb1 AFTER INSERT ON tb1 FOR EACH ROW
BEGIN
    ...
END

# 刪除前
CREATE TRIGGER tri_before_delete_tb1 BEFORE DELETE ON tb1 FOR EACH ROW
BEGIN
    ...
END

# 刪除後
CREATE TRIGGER tri_after_delete_tb1 AFTER DELETE ON tb1 FOR EACH ROW
BEGIN
    ...
END

# 更新前
CREATE TRIGGER tri_before_update_tb1 BEFORE UPDATE ON tb1 FOR EACH ROW
BEGIN
    ...
END

# 更新後
CREATE TRIGGER tri_after_update_tb1 AFTER UPDATE ON tb1 FOR EACH ROW
BEGIN
    ...
END

觸發器沒法由用戶直接調用,而由對錶的操做被動引起的

刪除觸發器

drop trigger newproduct;

存儲過程

存儲過程包含了一系列可執行的SQL語句,存儲過程放於MySQL中,經過調用它的名字能夠執行其內部的一堆SQL

存儲過程的優勢:

  • 用於替代程序寫的SQL語句,實現程序與SQL的解耦

  • 基於網絡的傳輸,傳別名的數據量小,而直接傳sql數據量大

缺點:

  • 程序員擴展功能不方便

建立無參存儲過程

delimiter //
create procedure p1()
BEGIN
    select * from blog;
    INSERT into blog(name,sub_time) values("xxx",now());
END //
delimiter ;

#在mysql中調用
call p1() 

#在python中基於pymysql調用
cursor.callproc('p1') 
print(cursor.fetchall())

建立有參存儲過程

對於存儲過程,能夠接收參數,其參數有三種:

in 僅用於傳入參數用

out 用於返回值

inout 既能夠傳入又能夠看成返回值

# in:傳入參數
delimiter //
create procedure p2(
    in n1 int,
    in n2 int
)
BEGIN
    
    select * from blog where id > n1;
END //
delimiter ;

#在mysql中調用
call p2(3,2)

#在python中基於pymysql調用
cursor.callproc('p2',(3,2))
print(cursor.fetchall())
# out:返回值
delimiter //
create procedure p3(
    in n1 int,
    out res int
)
BEGIN
    select * from blog where id > n1;
    set res = 1;
END //
delimiter ;

#在mysql中調用
set @res=0; #0表明假(執行失敗),1表明真(執行成功)
call p3(3,@res);
select @res;

#在python中基於pymysql調用
cursor.callproc('p3',(3,0)) #0至關於set @res=0
print(cursor.fetchall()) #查詢select的查詢結果

cursor.execute('select @_p3_0,@_p3_1;') #@p3_0表明第一個參數,@p3_1表明第二個參數,即返回值
print(cursor.fetchall())
# inout:既能夠傳入又能夠返回
delimiter //
create procedure p4(
    inout n1 int
)
BEGIN
    select * from blog where id > n1;
    set n1 = 1;
END //
delimiter ;

#在mysql中調用
set @x=3;
call p4(@x);
select @x;


#在python中基於pymysql調用
cursor.callproc('p4',(3,))
print(cursor.fetchall()) #查詢select的查詢結果

cursor.execute('select @_p4_0;') 
print(cursor.fetchall())

執行存儲過程

在MySQL中執行:

-- 無參數
call proc_name()

-- 有參數,全in
call proc_name(1,2)

-- 有參數,有in,out,inout
set @t1=0;
set @t2=3;
call proc_name(1,2,@t1,@t2)

在python中基於pymysql執行:

#!/usr/bin/env python
# -*- coding:utf-8 -*-
import pymysql

conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='123', db='t1')
cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
# 執行存儲過程
cursor.callproc('p1', args=(1, 22, 3, 4))
# 獲取執行完存儲的參數
cursor.execute("select @_p1_0,@_p1_1,@_p1_2,@_p1_3")
result = cursor.fetchall()

conn.commit()
cursor.close()
conn.close()


print(result)

刪除存儲過程

drop procedure proc_name;

SQL函數

MySQL提供了許多內置函數

CHAR_LENGTH(str)
        返回值爲字符串str 的長度,長度的單位爲字符。一個多字節字符算做一個單字符。
        對於一個包含五個二字節字符集, LENGTH()返回值爲 10, 而CHAR_LENGTH()的返回值爲5。
    
    CONCAT(str1,str2,...)
        字符串拼接
        若有任何一個參數爲NULL ,則返回值爲 NULL。
    FORMAT(X,D)
        將數字X 的格式寫爲'#,###,###.##',以四捨五入的方式保留小數點後 D 位, 並將結果以字符串的形式返回。若 D 爲 0, 則返回結果不帶有小數點,或不含小數部分。
        例如:
            SELECT FORMAT(12332.1,4); 結果爲: '12,332.1000'
    INSTR(str,substr)
        返回字符串 str 中子字符串的第一個出現位置。
    LEFT(str,len)
        返回字符串str 從開始的len位置的子序列字符。
    LOWER(str)
        變小寫
    UPPER(str)
        變大寫
    LTRIM(str)
        返回字符串 str ,其引導空格字符被刪除。
    RTRIM(str)
        返回字符串 str ,結尾空格字符被刪去。
    SUBSTRING(str,pos,len)
        獲取字符串子序列
    LOCATE(substr,str,pos)
        獲取子序列索引位置
    REPEAT(str,count)
        返回一個由重複的字符串str 組成的字符串,字符串str的數目等於count 。
        若 count <= 0,則返回一個空字符串。
        若str 或 count 爲 NULL,則返回 NULL 。
    REPLACE(str,from_str,to_str)
        返回字符串str 以及全部被字符串to_str替代的字符串from_str 。
    REVERSE(str)
        返回字符串 str ,順序和字符順序相反。
    RIGHT(str,len)
        從字符串str 開始,返回從後邊開始len個字符組成的子序列
相關文章
相關標籤/搜索