mysql的視圖,觸發器,存儲過程,函數,事物,數據庫鎖,數據庫的備份還原
視圖
視圖:是一個虛擬表,其內容由查詢定義。同真實的表一樣,視圖包含一系列帶有名稱的列和行數據
視圖有如下特點;
1. 視圖的列可以來自不同的表,是表的抽象和邏輯意義上建立的新關系。
2. 視圖是由基本表(實表)產生的表(虛表)。
3. 視圖的建立和刪除不影響基本表。
4. 對視圖內容的更新(添加、刪除和修改)直接影響基本表。
5. 當視圖來自多個基本表時,不允許添加,修改和刪除數據。
語法:
創建視圖
create view 視圖名稱 as sql 查詢語句
使用視圖
select * from 視圖名稱;
更新視圖
alter view 視圖名稱 ASSQL語句
刪除視圖
drop view ren_view;
觸發器
觸發器:監視某種情況,並觸發某種操作。
觸發器創建語法四要素:1.監視地點(table)
2.監視事件(insert/update/delete)
3.觸發時間(after/before)
4.觸發事件(insert/update/delete)
觸發器創建
create
trigger
triggerName
after
/before
insert
/
update
/
delete
on
表名
for
each row #這句話是固定的
begin
#需要執行的sql語句
end
註意1:
after
/before: 只能選一個 ,
after
表示 後置觸發, before 表示前置觸發
註意2:
insert
/
update
/
delete
:只能選一個
比如
create
trigger
tg1
after
insert
on
order_table
for
each row
begin
update
goods
set
num = num -3
where
id = 1;
end
觸發器·的啟動(觸動觸發器)
insert
into
order_table(gid,much)
values
(1,3);
我們如何在觸發器引用行的值,也就是說我們要得到我們新插入的訂單記錄中的gid或much的值。
對於insert而言,新插入的行用new來表示,行中的每一列的值用new.列名來表示。
所以現在我們可以這樣來改我們的觸發器:
create trigger tg2 after insert on order_table for each row begin update goods set num = num-new.much where id = new.gid; end
觸發器的刪除
drop trigger tg1;
存儲過程
MySQL數據庫在5.0版本後開始支持存儲過程,那麽什麽是存儲過程呢?怎麽創建、查看和刪除存儲過程呢?存儲過程有什麽優點?
存儲過程:類似於函數(方法),簡單的說存儲過程是為了完成某個數據庫中的特定功能而編寫的語句集合,該語句集包括SQL語句(對數據的增刪改查)、條件語句和循環語句等。
查看所有的存儲
show procedure status;
刪除存儲過程
drop procedure 存儲過程名稱;
調用
drop procedure 存儲過程名稱;
4.創建存儲過程
create procedure p2(in i int,out n varchar(50)) begin select name into n from account where id = i; end -- 調用 set @name =null; CALL p2(1,@name); select @name;
當傳參的參數是非int類型時必須要先將該參數定義一個名稱
註意1: mysql中有三種出入參數類型:分別為:1. in 入參類型 2.out 出參類型 3. inout 出入參類型
註意2: into 關鍵字 可以 將前面字段的查詢結果 執行 給 into 後面的變量.
#4.體會循環:計算1-100累加的和,並且返回計算結果. create procedure p4(inout n int) begin DECLARE sum int default 0; -- 設置總和變量,並且指定初始值0 declare i int; -- 聲明變量 set i = 0; -- 通過set為變量設置值 while i<=n DO -- 開始循環 set sum = sum +i; set i = i+1; end while; -- 結束循環 select sum; -- 提供結果 set n = sum;--將計算結果提供給 輸出變量 n; end; -- 調用: set @n = 100; call p4(@n); select @n;
存儲過程優點: 1、存儲過程增強了SQL語言靈活性。 存儲過程可以使用控制語句編寫,可以完成復雜的判斷和較復雜的運算,有很強的靈活性; 2、減少網絡流量,降低了網絡負載。 存儲過程在服務器端創建成功後,只需要調用該存儲過程即可,而傳統的做法是每次都將大量的SQL語句通過網絡發送至數據庫服務器端然後再執行 3、存儲過程只在創造時進行編譯,以後每次執行存儲過程都不需再重新編譯。 一般SQL語句每執行一次就編譯一次,所以使用存儲過程可提高數據庫執行速度。
存儲過程缺點:
1、擴展功能不方便
2、不便於系統後期維護
函數:
MySQL提供的內建函數:
一、數學函數 ROUND(x,y) 返回參數x的四舍五入的有y位小數的值 RAND() 返回0到1內的隨機值,可以通過提供一個參數(種子)使RAND()隨機數生成器生成一個指定的值。 二、聚合函數(常用於GROUP BY從句的SELECT查詢中) AVG(col)返回指定列的平均值 COUNT(col)返回指定列中非NULL值的個數 MIN(col)返回指定列的最小值 MAX(col)返回指定列的最大值 SUM(col)返回指定列的所有值之和 GROUP_CONCAT(col) 返回由屬於一組的列值連接組合而成的結果 三、字符串函數 CHAR_LENGTH(str) 返回值為字符串str 的長度,長度的單位為字符。一個多字節字符算作一個單字符。 CONCAT(str1,str2,...) 字符串拼接 如有任何一個參數為NULL ,則返回值為 NULL。 CONCAT_WS(separator,str1,str2,...) 字符串拼接(自定義連接符) CONCAT_WS()不會忽略任何空字符串。 (然而會忽略所有的 NULL)。 FORMAT(X,D) 將數字X 的格式寫為‘#,###,###.##‘,以四舍五入的方式保留小數點後 D 位, 並將結果以字符串的形式返回。若 D 為 0, 則返回結果不帶有小數點,或不含小數部分。 例如: SELECT FORMAT(12332.1,4); 結果為: ‘12,332.1000‘ INSERT(str,pos,len,newstr) 在str的指定位置插入字符串 pos:要替換位置其實位置 len:替換的長度 newstr:新字符串 例如: SELECT INSERT(‘abcd‘,1,2,‘tt‘); 結果為: ‘ttcd‘ SELECT INSERT(‘abcd‘,1,4,‘tt‘); 結果為: ‘tt‘ 特別的: 如果pos超過原字符串長度,則返回原字符串 如果len超過原字符串長度,則由新字符串完全替換 INSTR(str,substr) 返回字符串 str 中子字符串的第一個出現位置。 LEFT(str,len) 返回字符串str 從開始的len位置的子序列字符。 例如: SELECT INSTR(‘abc‘,‘c‘); 結果為: 3 SELECT INSTR(‘abc‘,‘d‘); 結果為: 0 LOWER(str) 變小寫 UPPER(str) 變大寫 REVERSE(str) 返回字符串 str ,順序和字符順序相反。 例如: SELECT REVERSE(‘1234567‘) 結果為:7654321 SUBSTRING(str,pos) , SUBSTRING(str FROM pos) SUBSTRING(str,pos,len) , SUBSTRING(str FROM pos FOR len) 不帶有len 參數的格式從字符串str返回一個子字符串,起始於位置 pos。帶有len參數的格式從字符串str返回一個長度同len字符相同的子字符串,起始於位置 pos。 使用 FROM的格式為標準 SQL 語法。也可能對pos使用一個負值。假若這樣,則子字符串的位置起始於字符串結尾的pos 字符,而不是字符串的開頭位置。在以下格式的函數中可以對pos 使用一個負值。 mysql> SELECT SUBSTRING(‘Quadratically‘,5); -- 從第5位開始截取 -> ‘ratically‘ mysql> SELECT SUBSTRING(‘foobarbar‘ FROM 4); -- 從第4位開始截取 -> ‘barbar‘ mysql> SELECT SUBSTRING(‘Quadratically‘,5,6); --從第5位開始截取,截取6個長度 -> ‘ratica‘ mysql> SELECT SUBSTRING(‘Sakila‘, -3); -- 從倒數第3位開始截取 -> ‘ila‘ mysql> SELECT SUBSTRING(‘Sakila‘, -5, 3); -- 從倒數第5位開始截取,截取3個長度 -> ‘aki‘ 四、日期和時間函數 CURDATE()或CURRENT_DATE() 返回當前的日期 CURTIME()或CURRENT_TIME() 返回當前的時間 DAYOFWEEK(date) 返回date所代表的一星期中的第幾天(1~7) DAYOFMONTH(date) 返回date是一個月的第幾天(1~31) DAYOFYEAR(date) 返回date是一年的第幾天(1~366) DAYNAME(date) 返回date的星期名,如:SELECT DAYNAME(CURRENT_DATE); FROM_UNIXTIME(ts,fmt) 根據指定的fmt格式,格式化UNIX時間戳ts HOUR(time) 返回time的小時值(0~23) MINUTE(time) 返回time的分鐘值(0~59) MONTH(date) 返回date的月份值(1~12) MONTHNAME(date) 返回date的月份名,如:SELECT MONTHNAME(CURRENT_DATE); NOW() 返回當前的日期和時間 QUARTER(date) 返回date在一年中的季度(1~4),如SELECT QUARTER(CURRENT_DATE); WEEK(date) 返回日期date為一年中第幾周(0~53) YEAR(date) 返回日期date的年份(1000~9999) 重點: DATE_FORMAT(date,format) 根據format字符串格式化date值 mysql> SELECT DATE_FORMAT(‘2009-10-04 22:23:00‘, ‘%W %M %Y‘); -> ‘Sunday October 2009‘ mysql> SELECT DATE_FORMAT(‘2007-10-04 22:23:00‘, ‘%H:%i:%s‘); -> ‘22:23:00‘ mysql> SELECT DATE_FORMAT(‘1900-10-04 22:23:00‘, -> ‘%D %y %a %d %m %b %j‘); -> ‘4th 00 Thu 04 10 Oct 277‘ mysql> SELECT DATE_FORMAT(‘1997-10-04 22:23:00‘, -> ‘%H %k %I %r %T %S %w‘); -> ‘22 22 10 10:23:00 PM 22:23:00 00 6‘ mysql> SELECT DATE_FORMAT(‘1999-01-01‘, ‘%X %V‘); -> ‘1998 52‘ mysql> SELECT DATE_FORMAT(‘2006-06-00‘, ‘%d‘); -> ‘00‘ 五、加密函數 MD5() 計算字符串str的MD5校驗和 例如: SELECT MD5(‘1234‘) 結果為:81dc9bdb52d04dc20036dbd8313ed055 PASSWORD(str) 返回字符串str的加密版本,這個加密過程是不可逆轉的 例如: SELECT PASSWORD(‘1234‘) 結果為:*A4B6157319038724E3560894F7F932C8886EBFCF 六、控制流函數 CASE WHEN[test1] THEN [result1]...ELSE [default] END 如果testN是真,則返回resultN,否則返回default CASE [test] WHEN[val1] THEN [result]...ELSE [default]END 如果test和valN相等,則返回resultN,否則返回default IF(test,t,f) 如果test是真,返回t;否則返回f IFNULL(arg1,arg2) 如果arg1不是空,返回arg1,否則返回arg2 例如: SELECT IFNULL(‘bbb‘,‘abc‘); 結果為: bbb SELECT IFNULL(null,‘abc‘); 結果為: abc NULLIF(arg1,arg2) 如果arg1=arg2返回NULL;否則返回arg1 例如: SELECT NULLIF(‘bbb‘,‘bbb‘);結果為: null SELECT NULLIF(‘aaa‘,‘bbb‘);結果為: aaa
等
自定義函數
CREATE FUNCTION fun1(i1 int,i2 int) RETURNS INT //設置返回類型 BEGIN DECLARE sum int default 0; set sum = i1+i2; RETURN(sum); //返回結果 end
調用
#直接調用自定義函數 select fun1(1,5); #在sql語句中使用自定義函數 select fun1(參數1,參數2),name from 表名
刪除
DROP FUNCTION fun_name;
事物
一、 什麽是事務
一組sql語句批量執行,要麽全部執行成功,要麽全部執行失敗
二、為什麽出現這種技術
為什麽要使用事務這個技術呢? 現在的很多軟件都是多用戶,多程序,多線程的,對同一個表可能同時有很多人在用,為保持數據的一致性,所以提出了事務的概念。這樣很抽象,舉個例子:
A 給B 要劃錢,A 的賬戶-1000元, B 的賬戶就要+1000元,這兩個update 語句必須作為一個整體來執行,不然A 扣錢了,B 沒有加錢這種情況很難處理。
三、事物的特性
80年代中國人結婚四大件:手表、自行車、縫紉機、收音機(三轉一響)。要把事務娶回家同樣需要四大件,所以事務很刻薄(ACID),四大件清單:原子性(Atom)、一致性(Consistent)、隔離性(Isolate)、持久性(Durable)。ACID就是數據庫事務正確執行的四個特性的縮寫。
- 原子性:要麽不談,要談就要結婚!
對於其數據修改,要麽全都執行,要麽全都不執行。
- 一致性:戀愛時,什麽方式愛我;結婚後還得什麽方式愛我;
數據庫原來有什麽樣的約束,事務執行之後還需要存在這樣的約束,所有規則都必須應用於事務的修改,以保持所有數據的完整性。
- 隔離性:鬧完洞房後,是倆人的私事。
一個事務不能知道另外一個事務的執行情況(中間狀態)
- 持久性:一旦領了結婚證,無法後悔。
即使出現致命的系統故障也將一直保持。不要告訴我系統說commit成功了,回頭電話告訴我,服務器機房斷電了,我的事務涉及到的數據修改可能沒有進入數據庫。
另外需要註意:
- 在 MySQL 中只有使用了 Innodb 數據庫引擎的數據庫或表才支持事務。
- 事務處理可以用來維護數據庫的完整性,保證成批的 SQL 語句要麽全部執行,要麽全部不執行。
- 事務用來管理 insert,update,delete 語句
四、事務控制語句:
-
BEGIN 或 START TRANSACTION;顯式地開啟一個事務;
-
COMMIT;也可以使用COMMIT WORK,不過二者是等價的。COMMIT會提交事務,並使已對數據庫進行的所有修改稱為永久性的;
-
ROLLBACK;有可以使用ROLLBACK WORK,不過二者是等價的。回滾會結束用戶的事務,並撤銷正在進行的所有未提交的修改;
- SAVEPOINT : 保存點,可以把一個事物分割成幾部分.在執行ROLLBACK 時 可以指定在什麽位置上進行回滾操作.
註意: SET AUTOCOMMIT=0 ;禁止自動提交 和 SET AUTOCOMMIT=1 開啟自動提交.
鎖
1. 鎖的基本概念
當並發事務同時訪問一個資源時,有可能導致數據不一致,因此需要一種機制來將數據訪問順序化,以保證數據庫數據的一致性。
2. 鎖的基本類型
多個事務同時讀取一個對象的時候,是不會有沖突的。同時讀和寫,或者同時寫才會產生沖突。因此為了提高數據庫的並發性能,通常會定義兩種鎖:共享鎖和排它鎖。
2.1 共享鎖(Shared Lock,也叫S鎖)
共享鎖(S)表示對數據進行讀操作。因此多個事務可以同時為一個對象加共享鎖。(如果試衣間的門還沒被鎖上,顧客都能夠同時進去參觀)
2.2 排他鎖(Exclusive Lock,也叫X鎖)
排他鎖(X)表示對數據進行寫操作。如果一個事務對 對象加了排他鎖,其他事務就不能再給它加任何鎖了。(某個顧客把試衣間從裏面反鎖了,其他顧客想要使用這個試衣間,就只有等待鎖從裏面給打開了).
3. 實際開發中常見的兩種鎖:
3.1悲觀鎖 顧名思義,就是很悲觀,每次去拿數據的時候都認為別人會修改,所以每次在拿數據的時候都會上鎖,這樣別人想拿這個數據就會block(阻塞)直到它拿到鎖。傳統的關系型數據庫裏邊就用到了很多這種鎖機制.
註意:要使用悲觀鎖,我們必須關閉mysql數據庫的自動提交屬性.因為MySQL默認使用autocommit模式,也就是說,當你執行一個更新操作後,MySQL會立刻將結果進行提交。關閉自動提交命令為:set autocommit=0;
例子
-- 0.開始事務 start transaction; -- 1.查詢賬戶余額 set @m = 0; -- 賬戶余額 select money into @m from account where id = 1 for update; select @m; -- 2.修改賬戶余額 update account set money = @m -100 where id = 1; select * FROM account where id = 1; -- 3. 提交事務 commit;
會發現當前查詢會進入到等待狀態,不會顯示出數據,當上面的sql執行完畢提交事物後,當前sql才會顯示結果.
註意1:在使用悲觀鎖時,如果表中沒有指定主鍵,則會進行鎖表操作.
註意2: 悲觀鎖的確保了數據的安全性,在數據被操作的時候鎖定數據不被訪問,但是這樣會帶來很大的性能問題。因此悲觀鎖在實際開發中使用是相對比較少的。
3.2 樂觀鎖, 顧名思義,就是很樂觀,每次去拿數據的時候都認為別人不會修改,所以不會上鎖,但是在更新的時候會判斷一下在此期間別人有沒有去更新這個數據,可以使用版本號等機制。
使用樂觀鎖的兩種方式:
1.使用數據版本(Version)記錄機制實現,這是樂觀鎖最常用的一種實現 方式。何謂數據版本?即為數據增加一個版本標識,一般是通過為數據庫表增加一個數字類型的 “version” 字段來實現。當讀取數據時,將version字段的值一同讀出,數據每更新一次,對此version值加一。當我們提交更新的時候,判斷數據庫表對應記錄 的當前版本信息與第一次取出來的version值進行比對,如果數據庫表當前版本號與第一次取出來的version值相等,則予以更新,否則認為是過期數 據。
代碼示例:
-- 1.查詢賬戶余額 set @m = 0; -- 賬戶余額 select money into @m from account where id = 1 ; select @m; -- 2.查詢版本號 set @version = 0; -- 版本號 select version into @version from account where id = 1 ; select @version; -- 3.修改賬戶余額 update account set money = @m -100,version=version+1 where id = 1 and version = @version; select * FROM account where id = 1;
2.樂觀鎖定的第二種實現方式和第一種差不多,同樣是在需要樂觀鎖控制的table中增加一個字段,名稱無所謂,字段類型使用時間戳 (datatime), 和上面的version類似,也是在更新提交的時候檢查當前數據庫中數據的時間戳和自己更新前取到的時間戳進行對比,如果一致則OK,否則就是版本沖突。
悲觀鎖與樂觀鎖的優缺點:
兩種鎖各有其有點缺點,不能單純的講哪個更好.
樂觀鎖適用於寫入比較少的情況下,即沖突真的很少發生的時候,這樣可以省去了鎖的開銷,加大了系統的整個吞吐量。
但如果經常產生沖突,上層應用會不斷的進行重試操作,這樣反倒是降低了性能,所以這種情況下用悲觀鎖就比較合適.
數據庫的備份還原(建議使用可視化軟件操作)
mysql的視圖,觸發器,存儲過程,函數,事物,數據庫鎖,數據庫的備份還原