mysql數據庫—事務、存儲過程


視圖

什么是試圖

試圖是由一張表或多張表的查詢結果構成的一張虛擬表

為什么使用視圖

我們在使用多表查詢時 我們的sql語句可能會非常的復雜,如果每次都編寫一遍sql'的話無疑是一件麻煩的事情,這時候就可以使用視圖來避免多次編寫sql的問題;

簡答的說可以幫我們節省sql的編寫,

視圖的另一個作用是,可以不同的視圖來展示開放不同數據的訪問

例如,同一張工資表,老板可以查看全部,部門主管可以查看該部門所有人,員工只能看自己的一條記錄

使用方法

語法:
create [or replace] view view_name as 查詢語句;
or replace 如果視圖已經存在了 就替換里面的查詢語句;

# 修改視圖
alter view view_name  as 新的語句;

# 刪除視圖
drop view  view_name;

# 查看
desc view_name;
show create view view_name;



# 限制可以查看的記錄 
create table salarys(id int,name char(10),money float);
insert into salarys values(1,"張三豐",50000),(2,"張無忌",40000);
# 創建視圖  限制只能查看張無忌的工資
create view zwj_view as select *from salarys where name = "張無忌";

# 簡化sql編寫
create table student(
  s_id int(3),
  name varchar(20), 
  math float,
  chinese float 
);
insert into student values(1,'tom',80,70),(2,'jack',80,80),(3,'rose',60,75);

create table stu_info(
  s_id int(3),
  class varchar(50),
  addr varchar(100)
);
insert into stu_info values(1,'二班','安徽'),(2,'二班','湖南'),(3,'三班','黑龍江');
# 查詢班級和學員的對應關系做成一個視圖  方便后續的查詢 
create view class_info as select student.s_id,name,class from student join stu_info on student.s_id = stu_info.s_id;

select *from class_info;

注意: 修改視圖 也會引起原表的變化,我們不要這么做,視圖僅用於查詢

觸發器

什么是觸發器

觸發器是一段與表有關的mysql程序
當這個表在某個時間點發生了某種事件時 將會自動執行相應的觸發器程序

創建觸發器

語法:

create trigger t_name  t_time t_event on  table_name for each row 
begin
#sql語句。。。。。:
end

案例:

#准備數據
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
);

#需求: 當插入cmd表 的時候 如果執行狀態時失敗的 那么將信息插入到errlog中

# 將結束符設置為|
delimiter |
create trigger cmd_insert after insert on cmd for each row
begin
if new.success = "no" then
	insert into errlog values(null,new.cmd,new.sub_time);
end if;
end|
# 在還原之前的結束符 
delimiter ;


# 創建一個觸發器 叫cmd_insert  
# 觸發器會在 插入數據到cmd表后執行 
# 當插入的記錄的success為no時 自動插入記錄到errlog中 


# 錯誤原因 遇到分號自動提交了  , 需要重定義  行結束符  
delimiter |

# 刪除觸發器
drop trigger cmd_insert;

#查看 所有觸發器
show triggers;

# 查看某個觸發器的語句 
show create trigger t_name;

事務

什么是事務

事務就是一系列sql語句的組合,是一個整體

為什么要有事務

很多時候一個數據操作,不是一個sql語句就完成的,可能有很多個sql語句,如果部分sql執行成功而部分sql執行失敗將導致數據錯亂!

例如轉賬操作,

1.從原有賬戶減去轉賬金額

2.給目標賬戶加上轉賬金額

若中間突然斷電了或系統崩潰了,錢就不翼而飛了!

事務的四個特性:

原子性:

事務是一組不可分割的單位,要么同時成功,要么同時不成功

一致性:

事物前后的數據完整性應該保持一致,(數據庫的完整性:如果數據庫在某一時間點下,所有的數據都符合所有的約束,則稱數據庫為完整性的狀態);

隔離性:

事物的隔離性是指多個用戶並發訪問數據時,一個用戶的事物不能被其它用戶的事務所干擾,多個並發事務之間數據要相互隔離

持久性:

持久性是指一個事物一旦被提交,它對數據的改變就是永久性的,接下來即使數據庫發生故障也不應該對其有任何影響

使用事務

start transaction: 開啟事物,在這條語句之后的sql將處在同一事務,並不會立即修改數據庫

commit:提交事務,讓這個事物中的sql立即執行數據的操作,

rollback:回滾事務,取消這個事物,這個事物不會對數據庫中的數據產生任何影響

#開啟事務 
start transaction 
#sql 語句......
#sql 語句......
rollback  #回滾操作   即撤銷沒有提交之前的所有操作 
#sql 語句......
commit  #提交事務 一旦提交就持久化了


CREATE TABLE `account` (
  `name` char(10),
  `money` float  
);

start transaction;
update account set money = money - 100 where name = "一只穿雲箭";
update account set money = money + 100 where name = "千軍萬馬";
commit;


# 何時應該回滾  當一個事務執行過程中出現了異常時
# 何時提交   當事務中所有語句都執行成功時

# 保存點 可以在rollback指定回滾到某一個savepoint ,也就是回滾一部分  

start transaction;
update account set money = money - 100 where name = "一只穿雲箭";
savepoint a;
update account set money = money - 100 where name = "一只穿雲箭";
savepoint b;
update account set money = money - 100 where name = "一只穿雲箭";
savepoint c;

select * from account;

# 回滾至某個保存點a,b,c 
rollback to 保存點名稱(a,b,c)

read committed

修改隔離級別

數據庫使用者可以控制數據庫工作在哪個級別下,就可與防止不同的隔離性問題

read uncommitted --不做任何隔離,可能臟讀,幻讀

read committed----可以防止臟讀,不能防止不可重復讀,和幻讀,

Repeatable read --可以防止臟讀,不可重復讀,不能防止幻讀

Serializable--數據庫運行在串行化實現,所有問題都沒有,就是性能低

修改全局的  
 set global transaction isolation level read committed;
 或者:
 set @@tx_isolation = "asasasasas-read";
 修改局部
 set session transaction isolation level read committed;

 @@系統內置變量
 @表示用戶自定義的變量
 
 # 修改后重新連接服務器生效

存儲過程

什么是存儲過程

存儲過程是一組任意的sql語句集合,存儲在mysql中,調用存儲過程時將會執行其包含的所有sql語句;與python中函數類似;

為什么使用存儲過程

回顧觸發器與視圖都是為了簡化應用程序中sql語句的書寫,但是還是需要編寫,而存儲過程中可以包含任何的sql語句,包括視圖,事務,流程控制等,這樣一來,應用程序可以從sql語句中完全解放,mysql可以替代應用程序完成數據相關的的邏輯處理!

那我們以后都是用存儲過程不就完了?

三種開發方式對比

1.應用程序僅負責業務邏輯編寫,所有與數據相關的邏輯都交給mysql來完成,通過存儲過程(推薦使用)

優點:

應用程序與數據處理完解耦合,一堆復雜的sql被封裝成了一個簡單的存儲過程,考慮到網絡環境因素,效率高

應用程序開發者不需要編寫sql語句,開發效率高

缺點:

python語法與mysql語法區別巨大,學習成本高

並且各種數據庫的語法大不相同,所以移植性非常差

應用程序開發者與BDA的跨部門溝通成本高,造成整體效率低

2.應用程序不僅編寫業務邏輯,還需要編寫所有的sql語句

優點:擴展性高,對於應用程序開發者而言,擴展性和維護性相較於第一種都有所提高

缺點:sql語句過於復雜,導致開發效率低,且需要考慮sql'優化問題

3.應用程序僅負責業務邏輯,sql語句的編寫交給ORM框架,(常用解決方案)

優點:應用程序開發者不需要編寫sql語句,開發效率高

缺點:執行效率低,由於需要將對象的操作轉化為sql語句,且需要通過網絡發送大量sql

創建存儲過程

create procedure pro_name(p_Type p_name data_type)
begin
sql語句......流程控制
end

p_type 參數類型

in 表示輸入參數

out 表示輸出參數

inout表示既能輸入又能輸出

p_name 參數名稱

data_type 參數類型 可以是mysql支持的數據類型

案例:使用存儲過程完成對student表的查詢

delimiter //
create procedure p1(in m int,in n int,out res int)
begin
    select *from student where chinese > m and chinese < n;
    #select *from student where chineseXXX > m and chinese < n; 修改錯誤的列名以測試執行失敗
    set res = m+n;
end//
delimiter ;
set @res = 0;
#調用存儲過程
call p1(70,80,@res);
#查看執行結果
select @res;

存儲過程中的事務應用

存儲過程中支持任何的sql語句包括事務!

案例:模擬轉賬中發生異常,進行回滾

delimiter //
create PROCEDURE transfer(in aid int,in bid int,in m float,out res int)
BEGIN 
    DECLARE exit handler for sqlexception 
    BEGIN 
        # ERROR 
        set res = 1; 
        rollback; 
    END; 
    # exit 也可以換成continue 表示發生異常時繼續執行
    DECLARE exit handler for sqlwarning 
    BEGIN 
        # WARNING 
        set res = 2; 
        rollback; 
    END; 

    START TRANSACTION; 
    update account set money = money - 1000 where id = 1;
    update account set moneys = money - 1000 where id = 1; # moneys字段導致異常
    COMMIT; 

    # SUCCESS 
    set res = 0; #0代表執行成功
END //
delimiter ;


#在mysql中調用存儲過程
set @res=123;
call transfer(1,2,90,@res);
select @res;


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM