視圖
什么是試圖
試圖是由一張表或多張表的查詢結果構成的一張虛擬表
為什么使用視圖
我們在使用多表查詢時 我們的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;