1. 程式人生 > >資料庫學習之旅——實驗8

資料庫學習之旅——實驗8

本節介紹資料庫事務中的SQL SERVER 事務的定義

本實驗的目的:熟悉SQL SERVER 的事務控制語言,能夠熟練使用事務控制語言來編寫事務處理程式。

事務的原理解析:

1.事務的概念:

事務(TRANSACTION)是一組單一邏輯工作單元的操作集合,是採用高階資料操縱語言或程式語言書寫的使用者程式 ,並由事務開始BEGIN TRANSACTION 和事務結束END TRANSACTION 來界定全體操作的集合。

2.事務的性質::

資料庫管理系統為了實現資料庫系統的完整性,事務的ACID性質是資料庫事務處理的基礎,具有如下性質。

原子性:要求事務的全部操作要麼在資料庫中 全部正確地反映出來,要麼全部不反映。

一致性:資料庫中資料不因事務的執行而受到破壞,事務執行的結果應當使得資料庫由一種一致性達到另一種 新的一致性。資料的一致性保證資料庫的完整性。

隔離性:事務的併發執行與這些事務單獨執行的結果一樣。在多個事務併發時,各個事務不必關心其他事務的執行,如同在單個使用者環境下執行一樣。事務的隔離性是事務併發控制技術的基礎。

永續性:事務對資料庫的更新應永久的反映在資料庫中。一個事務一旦完成其全部操作之後,對資料庫所有更新操作的結果將在資料庫中永久存在,及時以後發生故障也應保留這個事務的執行結果。永續性的意義在於保證資料庫具有可恢復性。

以下是本次實驗的練習與習題答案:(school表在此並未發出,請參考之前的練習)

USE SCHOOL
--4.1.4實驗練習
--假設學校將學生的銀行卡 和校園卡進行了繫結,允許學生直接從銀行卡轉賬到校園卡中。假設某學號為05212222的學生需要從銀行卡中轉賬100元到校園卡中,編寫事務處理程式,實現這一操作。
--(1)採用隱式事務方式來實現事務程式設計。
UPDATE ICBC_CARD
SET RESTORED_MONEY = RESTORED_MONEY-100
WHERE STU_CARD_ID = '05212222'

UPDATE STU_CARD
SET REMAINED_MONEY = REMAINED_MONEY+100
WHERE CARD_ID = '05212222'
--*****注:以上的程式碼中採取隱式事務方法,如果對該學生的銀行卡資料更新成功,會自動向資料庫提交。假若後來對該學生 校園卡的資料更新未能成功,則會造成轉賬失敗,但前一操作已經提交,無法還原。這就可能造成對資料庫狀態與事實語義不一致。
--*****注:針對以上問題,需要設法將這若干條SQL語句組合成一個獨立的事務,這樣才能保證各個操作步驟要麼同時成功,要麼一起失敗。這就需要在之後的(2)中的顯式事務方法來處理該事務。


--(2)採用顯式事務使用者定義事務的方法來實現事務程式設計。
BEGIN TRAN
UPDATE ICBC_CARD
SET RESTORED_MONEY = RESTORED_MONEY-100
WHERE STU_CARD_ID = '05212222'

UPDATE STU_CARD
SET REMAINED_MONEY = REMAINED_MONEY+100
WHERE CARD_ID = '05212222'
COMMIT TRAN
--*****注:為了完全控制事務並定義多個操作步驟組成的邏輯工作單元,可以採用顯式使用者定義事務的方式來實現使用者期望的邏輯操作。


--(3)事務與批命令。
UPDATE COURSES SET HOUR = 96 WHERE CID = '10001'
INSERT TEACHERS VALUES('1234567890','MY','
[email protected]
',3000) SELECT TOP 10 * FROM TEACHERS(HOLDLOCK) GO --*****注:批處理是由一條或多條TRANSACT SQL 語句或命令組成,能夠成組的執行,用於向SQL SERVER 提交成組的TRANSACT SQL 的語句組,由GO語句來終止語句組。批處理經過整體編譯一次成為一個執行計劃,並一次將整個執行計劃執行完畢。 --*****注:出發皮命令沒有固有的事務性質,除顯式的定義由幾個語句構成的單個事務,否則批命令中的每條語句都是一個互相獨立的事務,每條語句單獨完成或單獨失敗,而且批命令中的一個事務失敗,不影響其他語句的執行。 --(4)巢狀事務的程式設計。 SELECT 'BEFORE TRANSACTION: ' AS HINT,@@TRANCOUNT AS TRANACTIONCOUNT BEGIN TRAN SELECT 'THE FIRST TRANSACTION STARTS: ' AS HINT,@@TRANCOUNT AS TRANACTIONCOUNT SELECT TOP 3 * FROM CHOICES BEGIN TRAN SELECT 'THE SECOND TRANSACTION STARTS: ' AS HINT,@@TRANCOUNT AS TRANACTIONCOUNT COMMIT TRAN SELECT 'THE SECOND TRANSACTION COMMITS: ' AS HINT,@@TRANCOUNT AS TRANACTIONCOUNT ROLLBACK TRAN SELECT 'THE FIRST TRANSACTION ROLLBACK: ' AS HINT,@@TRANCOUNT AS TRANACTIONCOUNT --*****注:巢狀事務主要是為了支援儲存過程中的一些事務,這些事務可以從事務中已有的程序中呼叫,也可以從沒有活動的事務程序中呼叫。巢狀事務隊伍COMMIT TRANSACTION語句的每個呼叫都對應 於最後執行的BEGIN TRANSACTION 語句,也就是最內層的事務。 --(5)在儲存過程、觸發器中使用事務程式設計。 CREATE TRIGGER TD_COURSE ON COURSES FOR DELETE AS DECLARE @INFO VARCHAR(255) SELECT @INFO = '觸發器中的事務資料為: ' +CONVERT(VARCHAR(2),@@TRANCOUNT) PRINT @INFO RETURN --*****注:觸發器是一種特殊型別的儲存過程,主要用於完成 資料庫中物件的完整性。在表中進行資料修改時自動執行,觸發器被視為執行資料修改事務的一部分,與資料修改語句在同一事務空間中執行。由於觸發器已經在事務情景中操作,因此事務中要的事務控制語句只有ROLLBACK或者SAVE TRAN,不需要發出BEGIN TRAN。 PRINT '刪除操作以前觸發器中的事務數為: ' +CONVERT(VARCHAR(2),@@TRANCOUNT); DELETE FROM COURSES WHERE CID = '10052' PRINT '刪除操作之後觸發器中的事務數為: ' +CONVERT(VARCHAR(2),@@TRANCOUNT); --*****注:以上程式碼為COURSES的刪除操作,建立一個觸發器,然後執行一個刪除操作,觀察事務數目的變化。在刪除操作執行的過程中,觸發器得到執行,而且事務的數目為1,這就驗證了是觸發器事務是資料修改事務的一部分。 CREATE PROCEDURE INSERTCOURSEINFO @COURSEID CHAR(10), @COURSENAME VARCHAR(30), @HOUR INT, @RETURNSTRING VARCHAR(100) AS BEGIN TRAN IF EXISTS(SELECT CID FROM COURSES WHERE CID = @COURSEID) BEGIN SELECT @RETURNSTRING = '課程資訊已經存在' GOTO ONERROR END --新增課程資訊 INSERT INTO COURSES VALUES(@COURSEID,@COURSENAME,@HOUR) IF @@ERROR<>0 BEGIN SELECT @RETURNSTRING = '新增課程資訊失敗' GOTO ONERROR END SELECT @RETURNSTRING = '新增課程資訊成功' COMMIT TRAN --錯誤處理 ONERROR: ROLLBACK TRAN --*****注:同樣以上程式碼為從事務中呼叫儲存的過程,也可以在儲存過程中啟動事務,而且這是經常在資料庫開發過程中應用到的。因為在儲存過程中使用事務,可以提高資料庫操作的效率,可以方便維護。 --(6)命令事務與事務儲存點。 --方法①: BEGIN TRAN TRAN_UPD_COURSES UPDATE COURSES SET HOUR = 60 WHERE CID = '10052' BEGIN TRAN TRAN_UPD_TEACHERS INSERT INTO TEACHERS VALUES('1234567890','ZS','[email protected]',3000) IF @@ERROR!=0 BEGIN --撤銷事務 ROLLBACK TRAN TRAN_UPD_TEACHERS PRINT '更新教師表失敗' RETURN END --提交內層事務 COMMIT TRAN TRAN_UPD_TEACHERS --提交外層事務 COMMIT TRAN TRAN_UPD_COURSES --*****注:在編寫大的儲存過程、唱的批處理,以及大量事務巢狀的時候,一個常見的問題就是程式碼的可讀性差。為了改進程式碼的可讀性,在進行事務程式設計的時候,可以對事務進行命名清晰的標誌事務,提示使用者程式碼的邏輯性。 --*****注:命名事務是通過在BEGIN TRAN 語句中為事務命名,來標誌整個事務邏輯的工作單元。通過對事務命名,使得每個事務都易於識別,這對於事務巢狀更加重要。 --方法②: BEGIN TRAN TRAN_UPD_COURSES UPDATE COURSES SET HOUR = 45 WHERE CID = '10052' --設定事務儲存點 SAVE TRAN TRAN_UPD_COURSES_DONE INSERT INTO TEACHERS VALUES('1234567890','ZS','[email protected]',3000) IF @@ERROR!=0 OR @@ROWCOUNT>1 BEGIN --撤銷事務 ROLLBACK TRAN TRAN_UPD_TEACHERS_DONE PRINT '更新教師表資訊失敗!' RETURN END --提交事務 COMMIT TRAN TRAN_UPD_COURSE --*****注:此方法是事務儲存點,事務儲存點提供一種在事務中標記用ROLLBACK撤銷事務工作點的方法。利用事務儲存點,可提交事務開始處至儲存點的部分事務,而將事務的其他部分撤銷。

執行結果請讀者自試。