LÝ THUYẾT:
TRANSACTION: là việc thực hiện một nhóm các câu lệnh, các câu lệnh này được thực thi một cách tuần tự và độc lập nhau. Nếu tất cả câc lệnh trong nhóm thực hiện thành công khi đó tất cả các sự thay đổi dữ liệu được thực hiện trong Transaction được lưu vào cơ sở dữ liệu (COMMIT). Tuy nhiên, nếu có một trong các lệnh của nhóm lệnh thực thi thất bại thì toàn bộ tiến trình sẽ thất bại, đồng nghĩa với việc dữ liệu phải ROLLBACK về trạng thái ban đầu.
Các tiêu chuẩn Transaction:
- Bảo toàn (Atomicity) - đảm bảo rằng tất cả các câu lệnh trong nhóm lệnh được thực thi thành công. Nếu không, transaction bị hủy bỏ tại thời điểm thất bại và tất cả các thao tác trước đó được khôi phục về trạng thái cũ.
- Nhất quán (Consistency) - đảm bảo rằng cơ sở dữ liệu thay đổi chính xác các trạng thái khi một transaction được thực thi thành công.
- Độc lập (Isolation) - cho phép các transaction hoạt động độc lập và minh bạch với nhau.
- Bền bỉ (Durability) - đảm bảo rằng kết quả của một transaction được commit vẫn tồn tại trong trường hợp lỗi hệ thống.
Transaction T-SQL tường minh có dạng (code mẫu đơn giản)
SET XACT_ABORT ON
BEGIN TRAN
BEGIN TRY
-- Lệnh 1
-- Lệnh 2
-- Lệnh ...
COMMIT
END TRY
BEGIN CATCH
ROLLBACK
END CATCH
Ý nghĩa các lệnh dùng để xử lý transaction.
- COMMIT - để lưu các thay đổi.
- ROLLBACK - để khôi phục lại các thay đổi.
- SAVEPOINT - tạo ra các điểm trong transaction để ROLLBACK.
- SET TRANSACTION - thiết lập các thuộc tính cho transaction.
Các lệnh điều khiển transaction chỉ được sử dụng với các lệnh thao tác dữ liệu DML như - INSERT, UPDATE và DELETE.
Noted: Chúng không thể được sử dụng trong lệnh CREATE TABLE hoặc DROP TABLE vì các hoạt động này được tự động được commit trong cơ sở dữ liệu.
Giao dịch lồng (nested transaction) là giao dịch được viết bên trong một giao dịch khác.
- Mỗi khi câu lệnh BEGIN TRAN được thực thi, hàm hệ thống @@TRANCOUNT được tăng thêm 1.
- Khi thực thi câu lệnh COMMIT TRAN.
- Nếu @@TRANCOUNT > 1, các thay đổi sẽ không được commit. Thay vào đó @@TRANCOUNT giảm đi 1.
- Nếu @@TRANCOUNT = 1, mọi thay đổi đã được thực hiện trên CSDL trong suốt giao dịch sẽ được commit và @@TRANCOUNT được gán bằng 0.
- Câu lệnh ROLLBACK TRAN roll-back toàn bộ các giao dịch đang hoạt động và thiết lập giá trị cho @@TRANCOUNT về 0
YÊU CẦU:
Bài 1: (Mục đích là làm quen với Transaction)
- Hiển thị mã phòng ban bằng 2, hiển thị Transaction count
- Thực hiện đổi tên (TENPHG) thành 'Phong KT 004'
- Thực hiện Rollback lại tên ban đầu (lúc chưa update ...set....)
Bài 2:
Yêu cầu sử dụng giao dịch kết hợp với try catch để chặn lỗi thực hiện 2 yêu cầu sau:
- Viết chương trình thêm một nhân viên mới. Nếu thêm nhân viên thành công thì thêm 1 thân nhân cho nhân viên vừa tạo.
- Viết chương trình thêm một công việc mới cho đề án số 1, đồng thời phân công nhân viên mói thêm ở câu trên đảm nhận công việc mới tạo.
THỰC HIỆN:
Bài 1:
- Hiển thị mã phòng ban bằng 2, hiển thị Transaction count
- Thực hiện đổi tên (TENPHG) thành 'Phong KT 004'
- Thực hiện Rollback lại tên ban đầu (lúc chưa update ...set....)
Code:
-- ban đầu chưa thay đổi (1)
SELECT * FROM PHONGBAN WHERE PHONGBAN.MAPHG = 2
SELECT @@TRANCOUNT AS dem_Tran
-- thực hiện sửa TENPHG thành 'Phong KT 004' (2)
BEGIN TRAN
UPDATE PHONGBAN
SET TENPHG = 'Phong KT 004'
WHERE MAPHG = 2
--COMMIT TRAN -- Sau khi commit, TRANCOUNT sẽ = 0
SELECT * FROM PHONGBAN WHERE PHONGBAN.MAPHG = 2 -- kiểm sau khi thực hiện lệnh update... set..
SELECT @@TRANCOUNT AS dem_Tran -- kiểm tra biến đếm
-- thực hiện Rollback và kiểm tra kết quả (3)
ROLLBACK TRAN -- RollBack thành không khi TRANCOUNT > 0
SELECT * FROM PHONGBAN WHERE PHONGBAN.MAPHG = 2
SELECT @@TRANCOUNT AS dem_Tran
Kết quả:
- (1) Ban đầu TRANCOUNT = 0
- (2) Khi thực hiện thay đổi tên TRANCOUNT tăng lên 1 đơn vị
- (3) Thực hiện Rollback thì TRANCOUNT sẽ thiết lập giá trị là 0
Bài 2:
Yêu cầu sử dụng giao dịch kết hợp với try catch để chặn lỗi thực hiện 2 yêu cầu sau:
- Viết chương trình thêm một nhân viên mới. Nếu thêm nhân viên thành công thì thêm 1 thân nhân cho nhân viên vừa tạo.
DECLARE @ma_nv NVARCHAR(9) = '2222'
SET XACT_ABORT ON
BEGIN TRAN
BEGIN TRY
INSERT INTO NHANVIEN ( [HONV] ,[TENLOT] ,[TENNV] ,[MANV] ,[NGSINH] ,[DCHI] ,[PHAI] ,[LUONG] ,[MA_NQL] ,[PHG] )
VALUES ('Van', 'Cong', 'Khanh', @ma_nv, '2000/10/10','Binh Duong','Nam',30000,'005', 5)
INSERT INTO THANNHAN ([MA_NVIEN] ,[TENTN],[PHAI],[NGSINH] ,[QUANHE] )
VALUES (@ma_nv, 'Nhan Nhan', 'Nam','2000/10/10','ban be') -- sửa @ma_nv thành 99999
PRINT 'Them THANH CONG'
COMMIT -- thực hiện lưu nếu cả 2 dòng lệnh thêm thành công
END TRY
BEGIN CATCH
ROLLBACK -- Nếu 1 trong 2 lệnh INSERT không thành công sẽ thông báo lỗi
PRINT 'Them THAT BAI'
END CATCH
DECLARE @is_error BIT = 0;
DECLARE @ma_nv NVARCHAR(9) = '77777';
SET XACT_ABORT ON
BEGIN TRAN
BEGIN TRY
INSERT INTO NHANVIEN ( [HONV] ,[TENLOT] ,[TENNV] ,[MANV] ,[NGSINH] ,[DCHI] ,[PHAI] ,[LUONG] ,[MA_NQL] ,[PHG] )
VALUES ('Van', 'Cong', 'Khanh', @ma_nv, '2000/10/10','Binh Duong','Nam',30000,'005', 5)
-- SELECT * FROM NHANVIEN WHERE MANV = @ma_nv
END TRY
BEGIN CATCH
SET @is_error = 1;
END CATCH
IF @is_error = 0
BEGIN
BEGIN TRY
INSERT INTO THANNHAN ([MA_NVIEN] ,[TENTN],[PHAI],[NGSINH] ,[QUANHE] )
VALUES (@ma_nv, 'Nhan Nhan', 'Nam','2000/10/10','ban be')
PRINT 'Them THANH CONG'
END TRY
BEGIN CATCH
ROLLBACK TRAN
PRINT 'Them vao bang (THANNHAN) THAT BAI'
END CATCH
END
ELSE
BEGIN
PRINT 'Them vao bang (NHANVIEN) THAT BAI'
END;
- Viết chương trình thêm một công việc mới cho đề án số 1, đồng thời phân công nhân viên mới thêm ở câu trên đảm nhận công việc mới tạo.
DECLARE
@ma_dean INT = 1
,@so_tt INT = 12,
@ma_nv NVARCHAR(9) = '111';
SET XACT_ABORT ON
BEGIN TRAN
BEGIN TRY
INSERT INTO CONGVIEC (MADA, STT, TEN_CONG_VIEC) VALUES (@ma_dean, @so_tt, 'Tin Hoc Van Phong')
INSERT INTO PHANCONG (MA_NVIEN, MADA, STT, THOIGIAN) VALUES (@ma_nv, @ma_dean, @so_tt,20)
COMMIT TRAN
PRINT 'Them THANH CONG'
END TRY
BEGIN CATCH
ROLLBACK TRAN
PRINT 'Them THAT BAI'
END CATCH
Tham khảo thêm tại đây
Xong!