1.為什麼要事務
假定張三的賬戶直接轉賬1000元到李四的賬戶
CREATE TABLE bank--創建顧客信息 ( customerName CHAR(10), --顧客姓名 currentMoney MONEY --當前余額 ) GO --添加約束 根據銀行規定,賬戶余額不能少於1元,否則視為銷戶 ALTER TABLE bank ADD CONSTRAINT CK_currentMoney CHECK(currentMoney>=1) GO INSERT INTO bank(customerName,currentMoney) VALUES('張三',1000) INSERT INTO bank(customerName,currentMoney) VALUES('李四',1)
目前兩個賬戶的余額總和為:1000+1=1001元
模擬實現轉賬 : 從張三的賬戶轉賬1000元到李四的賬戶
*--轉賬測試:張三轉賬1000元給李四--*/ --我們可能會這樣這樣編寫語句 --張三的賬戶少1000元,李四的賬戶多1000元 UPDATE bank SET currentMoney=currentMoney-1000 WHERE customerName='張三' UPDATE bank SET currentMoney=currentMoney+1000 WHERE customerName='李四' GO --再次查看轉賬後的結果。 SELECT * FROM bank GO
張三的賬戶沒有減少 但李四的賬戶卻多了1000元 1000+1001=2001元 總額多出了1000元!
--違反約束 執行失敗 UPDATE語句違反約束:余額>=1元
UPDATE bank SET currentMoney=currentMoney-1000
WHERE customerName='張三'
--繼續往下執行:執行成功,所以李四變為1001元
SET currentMoney=currentMoney+1000
WHERE customerName='李四'
事務(TRANSACTION)是作為單個邏輯工作單元執行的一系列操作 這些操作作為一個整體一起向系統提交,要麼都執行、要麼都不執行
事務是一個不可分割的工作邏輯單元
轉賬過程就是一個事務。 它需要兩條UPDATE語句來完成,這兩條語句是一個整體,如果其中任一條出現錯誤,則整個轉賬業務也應取消,兩個賬戶中的余額應恢復到原來的數據,從而確保轉賬前和轉賬後的余額不變,即都是1001元。
事務必須具備以下四個屬性,簡稱ACID 屬性:
原子性(Atomicity):事務是一個完整的操作。事務的各步操作是不可分的(原子的);要麼都執行,要麼都不執行
一致性(Consistency):當事務完成時,數據必須處於一致狀態
隔離性(Isolation):對數據進行修改的所有並發事務是彼此隔離的,這表明事務必須是獨立的,它不應以任何方式依賴於或影響其他事務
永久性(Durability):事務完成後,它對數據庫的修改被永久保持,事務日志能夠保持事務的永久性
T-SQL使用下列語句來管理事務:
開始事務:BEGIN TRANSACTION
提交事務:COMMIT TRANSACTION
回滾(撤銷)事務:ROLLBACK TRANSACTION
一旦事務提交或回滾,則事務結束。
判斷某條語句執行是否出錯:
使用全局變量@@ERROR;
@@ERROR只能判斷當前一條T-SQL語句執行是否有錯,為了判斷事務中所有T-SQL語句是否有錯,我們需要對錯誤進行累計;
如: SET @errorSum=@errorSum+@@error
了解事務的分類:
顯示事務:用BEGIN TRANSACTION明確指定事務的開始,這是最常用的事務類型
隱性事務:通過設置SET IMPLICIT_TRANSACTIONS ON 語句,將隱性事務模式設置為打開,下一個語句自動啟動一個新事務。當該事務完成時,再下一個
T-SQL 語句又將啟動一個新事務
自動提交事務:這是 SQL Server 的默認模式,它將每條單獨的 T-SQL 語句視為一個事務,如果成功執行,則自動提交;如果錯誤,則自動回滾
使用事務解決銀行轉賬問題
……關鍵語句講解……… BEGIN TRANSACTION /*--定義變量,用於累計事務執行過程中的錯誤--*/ DECLARE @errorSum INT SET @errorSum=0 --初始化為0,即無錯誤 /*--轉賬:張三的賬戶少1000元,李四的賬戶多1000元*/ UPDATE bank SET currentMoney=currentMoney-1000 WHERE customerName='張三' SET @errorSum=@errorSum+@@error UPDATE bank SET currentMoney=currentMoney+1000 WHERE customerName='李四' SET @errorSum=@errorSum+@@error --累計是否有錯誤 F @errorSum<>0 --如果有錯誤 BEGIN print '交易失敗,回滾事務' ROLLBACK TRANSACTION END ELSE BEGIN print '交易成功,提交事務,寫入硬盤,永久的保存' COMMIT TRANSACTION END GO print '查看轉賬事務後的余額' SELECT * FROM bank GO