Trigger trong SQL Server là một công cụ mạnh mẽ giúp tự động thực thi các đoạn mã SQL khi có sự kiện xảy ra trên một bảng cụ thể. Bài viết này sẽ cung cấp hướng dẫn chi tiết cách sử dụng Trigger thông qua các ví dụ thực tế trên database quản lý bán hàng (QuanLyBanHang), giúp bạn hiểu rõ và áp dụng hiệu quả vào các dự án của mình.
Database QuanLyBanHang bao gồm 9 bảng: NHACC, VATTU, DONDH, CTDONDH, PNHAP, CTPNHAP, PXUAT, CTPXUAT và TONKHO.
Mục Lục
Tổng Quan Về Trigger Trong SQL Server
Trigger là một loại stored procedure đặc biệt, tự động kích hoạt khi có sự kiện INSERT, UPDATE hoặc DELETE xảy ra trên một bảng. Trigger được sử dụng để duy trì tính toàn vẹn dữ liệu, kiểm soát các thao tác trên dữ liệu và thực hiện các tác vụ phức tạp khác.
Database Diagram Quản Lý Bán Hàng
Các Loại Trigger Phổ Biến
Có hai loại trigger chính trong SQL Server:
- AFTER Trigger: Kích hoạt sau khi sự kiện (INSERT, UPDATE, DELETE) đã xảy ra.
- INSTEAD OF Trigger: Thay thế sự kiện ban đầu.
Trong bài viết này, chúng ta sẽ tập trung vào AFTER Trigger.
Các Ví Dụ Về Trigger Trong Quản Lý Bán Hàng
Dưới đây là 3 ví dụ cụ thể về cách sử dụng trigger trong database QuanLyBanHang:
Câu 1: Tạo trigger khi update hoặc insert cột SLNhap của bảng CTPNHAP thì tổng số lượng nhập phải nhỏ hơn hoặc bằng tổng số lượng đặt của bảng CTDONDH.
Câu 2: Tạo trigger khi update cột SLNhap của bảng CTPNHAP thì cột TongSLN (Tổng số lượng nhập) của bảng TONKHO được cập nhật theo.
Câu 3: Tạo trigger khi update hoặc insert dữ liệu của bảng TONKHO, cột SLCuoi (Số lượng cuối) được tính theo công thức SLCuoi = SLDau + TongSLN – TongSLX.
Hướng Dẫn Thực Hiện Chi Tiết
Câu 1: Kiểm Tra Số Lượng Nhập So Với Số Lượng Đặt
Giải thích: Trigger này đảm bảo rằng tổng số lượng nhập của một vật tư không vượt quá tổng số lượng đã đặt cho vật tư đó. Điều này giúp ngăn chặn tình trạng nhập hàng vượt quá nhu cầu thực tế.
Câu lệnh tạo trigger:
CREATE TRIGGER TRG_CTPNHAP_SLNhap
ON CTPNHAP
AFTER INSERT, UPDATE
AS
BEGIN
-- Kiểm tra tổng số lượng nhập có vượt quá số lượng đặt hay không
IF EXISTS (
SELECT 1
FROM CTPNHAP ct
JOIN CTDONDH dh ON ct.SoDh = dh.SoDh AND ct.MaVTU = dh.MaVTU
WHERE ct.SLNhap > dh.SLDat
)
BEGIN
-- Nếu vượt quá, hủy thao tác và thông báo lỗi
RAISERROR('Tổng số lượng nhập không được vượt quá số lượng đặt.', 16, 1)
ROLLBACK TRANSACTION
END
END
Câu lệnh tạo trigger kiểm tra số lượng nhập
Giải thích câu lệnh:
CREATE TRIGGER TRG_CTPNHAP_SLNhap: Tạo một trigger với tên làTRG_CTPNHAP_SLNhap.ON CTPNHAP: Trigger này được kích hoạt trên bảngCTPNHAP.AFTER INSERT, UPDATE: Trigger này được kích hoạt sau khi có thao tác INSERT hoặc UPDATE trên bảngCTPNHAP.IF EXISTS (...): Kiểm tra xem có tồn tại bản ghi nào mà số lượng nhập (SLNhap) lớn hơn số lượng đặt (SLDat) hay không.RAISERROR(...): Nếu điều kiện trên đúng, hiển thị thông báo lỗi.ROLLBACK TRANSACTION: Hủy bỏ giao dịch hiện tại, ngăn không cho dữ liệu được thay đổi.
Trigger sau khi tạo thành công:
Trigger CTPNHAP_SLNhap đã được tạo thành công
Câu 2: Cập Nhật Tổng Số Lượng Nhập Trong Bảng TONKHO
Giải thích: Khi số lượng nhập của một vật tư thay đổi trong bảng CTPNHAP, trigger này sẽ tự động cập nhật tổng số lượng nhập (TongSLN) tương ứng trong bảng TONKHO. Điều này giúp đảm bảo tính nhất quán của dữ liệu giữa hai bảng.
Câu lệnh tạo trigger:
CREATE TRIGGER TRG_CTPNHAP_SLNhap_Update_TONKHO
ON CTPNHAP
AFTER UPDATE
AS
BEGIN
-- Cập nhật tổng số lượng nhập trong bảng TONKHO
UPDATE TONKHO
SET TongSLN = (
SELECT SUM(ct.SLNhap)
FROM CTPNHAP ct
JOIN PNHAP pn ON ct.SoPN = pn.SoPN
WHERE TONKHO.MaVTU = ct.MaVTU
AND YEAR(pn.NgayNhap) = YEAR(GETDATE())
AND MONTH(pn.NgayNhap) = MONTH(GETDATE())
)
WHERE EXISTS (SELECT 1 FROM inserted WHERE inserted.MaVTU = TONKHO.MaVTU);
END
Câu lệnh tạo trigger cập nhật tổng số lượng nhập
Giải thích câu lệnh:
CREATE TRIGGER TRG_CTPNHAP_SLNhap_Update_TONKHO: Tạo một trigger với tên làTRG_CTPNHAP_SLNhap_Update_TONKHO.ON CTPNHAP: Trigger này được kích hoạt trên bảngCTPNHAP.AFTER UPDATE: Trigger này được kích hoạt sau khi có thao tác UPDATE trên bảngCTPNHAP.UPDATE TONKHO ...: Cập nhật cộtTongSLNtrong bảngTONKHO.(SELECT SUM(ct.SLNhap) ...): Tính tổng số lượng nhập của vật tư từ bảngCTPNHAPvàPNHAPdựa trên điều kiện năm và tháng nhập hàng.WHERE EXISTS (SELECT 1 FROM inserted WHERE inserted.MaVTU = TONKHO.MaVTU): Đảm bảo rằng chỉ cập nhật những bản ghi trongTONKHOmà có mã vật tư (MaVTU) tồn tại trong bản ghi vừa được cập nhật (inserted) ở bảngCTPNHAP.
Câu 3: Tính Toán Số Lượng Cuối Trong Bảng TONKHO
Giải thích: Trigger này tự động tính toán số lượng cuối (SLCuoi) trong bảng TONKHO dựa trên số lượng đầu (SLDau), tổng số lượng nhập (TongSLN) và tổng số lượng xuất (TongSLX). Việc này giúp đảm bảo tính chính xác của thông tin tồn kho.
Câu lệnh tạo trigger:
CREATE TRIGGER TRG_TONKHO_Update_SLCuoi
ON TONKHO
AFTER INSERT, UPDATE
AS
BEGIN
-- Cập nhật số lượng cuối (SLCuoi)
UPDATE TONKHO
SET SLCuoi = SLDau + TongSLN - TongSLX
WHERE EXISTS (SELECT 1 FROM inserted WHERE inserted.MaVTU = TONKHO.MaVTU);
END
Kiểm Tra Hoạt Động Của Trigger
Để đảm bảo các trigger hoạt động đúng như mong đợi, chúng ta cần thực hiện các kiểm tra sau:
Kiểm Tra Trigger 1: Ngăn Chặn Nhập Vượt Quá Số Lượng Đặt
Số lượng đặt của vật tư DD01 là 18:
Số lượng đặt của vật tư DD01 là 18
Tổng số lượng nhập của vật tư DD01 là 13, không vượt quá số lượng đặt là 18:
Tổng số lượng nhập của vật tư DD01 là 13
Khi thay đổi số lượng nhập của vật tư DD01 từ 5 thành 15, tổng số lượng nhập lúc này là 23. Do đó, tổng số lượng nhập cao hơn số lượng đặt trong bảng CTDONDH (23 > 18).
Thay đổi số lượng nhập của vật tư DD01
Trigger ngăn chặn không cho thay đổi số lượng nhập:
Trigger ngăn chặn thay đổi số lượng nhập
Kiểm Tra Trigger 2: Cập Nhật Tổng Số Lượng Nhập Trong Bảng TONKHO
Khi chúng ta thay đổi số lượng nhập (SlNhap) của dòng 1 hoặc dòng 2 thì tổng số lượng nhập sẽ là 10. Mặc dù, dòng 3 cũng là vật tư DD02 nhưng số lượng nhập không được tính:
Thay đổi số lượng nhập của vật tư DD02
Dựa vào số phiếu nhập (SoPn) chúng ta biết được ngày nhập (NgayNhap). Và chúng ta dễ dàng nhận thấy chỉ có N001 và N002 có cùng tháng và cùng năm nhập là 01/2007.
Phiếu nhập và ngày nhập
Tại bảng TONKHO, mặc dù có 2 dòng cùng chứa vật tư (MaVTu) là DD02 nhưng chỉ có tổng số lượng nhập (TongSLN) của dòng 1 được cập nhật vì đúng năm tháng là 200701.
Bảng TONKHO sau khi cập nhật
Kết Luận
Sử dụng Trigger trong SQL Server là một cách hiệu quả để duy trì tính toàn vẹn dữ liệu và tự động hóa các tác vụ trong cơ sở dữ liệu. Bằng cách áp dụng các ví dụ và hướng dẫn trong bài viết này, bạn có thể xây dựng các trigger mạnh mẽ để quản lý dữ liệu trong hệ thống của mình một cách hiệu quả hơn. Hãy nhớ kiểm tra kỹ lưỡng các trigger sau khi tạo để đảm bảo chúng hoạt động đúng như mong đợi.
