Khi bạn tạo trình kích hoạt trong SQL Server, bạn có tùy chọn kích hoạt nó cùng với câu lệnh kích hoạt (tức là câu lệnh SQL đã kích hoạt trình kích hoạt) hoặc kích hoạt nó thay thế của tuyên bố đó.
Để kích hoạt trình kích hoạt thay thế của câu lệnh kích hoạt, hãy sử dụng INSTEAD OF
đối số.
Điều này trái ngược với việc sử dụng FOR
hoặc AFTER
tranh luận. Khi bạn sử dụng các đối số đó, trình kích hoạt chỉ kích hoạt khi tất cả các hoạt động được chỉ định trong câu lệnh SQL kích hoạt đã khởi chạy thành công.
Ví dụ
Tạo một bảng mẫu:
CREATE TABLE t1 (
id int IDENTITY(1,1) NOT NULL,
c1 int DEFAULT 0,
c2 int DEFAULT 0,
c3 int DEFAULT 0
);
Tạo trình kích hoạt:
CREATE TRIGGER trg_t1
ON t1
INSTEAD OF UPDATE
AS
UPDATE t1
SET c3 = c3 + 1
WHERE id IN (SELECT DISTINCT id FROM inserted);
Chèn một hàng mẫu:
INSERT INTO t1 (c1, c2, c3)
VALUES (1, 1, 1);
SELECT * FROM t1;
Đây là những gì chúng tôi có cho đến nay:
+------+------+------+------+ | id | c1 | c2 | c3 | |------+------+------+------| | 1 | 1 | 1 | 1 | +------+------+------+------+
Bây giờ chúng ta hãy chạy một UPDATE
câu lệnh chống lại bảng (điều này sẽ kích hoạt trình kích hoạt).
UPDATE t1
SET c1 = c1 + 1
WHERE id = 1;
SELECT * FROM t1;
Kết quả:
+------+------+------+------+ | id | c1 | c2 | c3 | |------+------+------+------| | 1 | 1 | 1 | 2 | +------+------+------+------+
Như mong đợi, UPDATE
câu lệnh trong câu lệnh kích hoạt đã được thay thế bằng câu lệnh trong câu lệnh kích hoạt.
Trình kích hoạt của tôi đã chỉ định rằng bất kỳ khi nào có một nỗ lực cập nhật bảng, hãy cập nhật c3
thay vào đó.
Chỉ chạy khi một cột cụ thể được cập nhật
Bạn cũng có thể sử dụng UPDATE()
chức năng chỉ định mã chỉ chạy khi một cột cụ thể được cập nhật.
Ví dụ:chúng tôi có thể thay đổi trình kích hoạt của mình như sau:
ALTER TRIGGER trg_t1
ON t1
INSTEAD OF UPDATE
AS
IF ( UPDATE(c1) )
BEGIN
UPDATE t1
SET c3 = c3 + 1
WHERE id IN (SELECT DISTINCT id FROM inserted)
END;
Bây giờ hãy chạy UPDATE
trước đó tuyên bố một lần nữa:
UPDATE t1
SET c1 = c1 + 1
WHERE id = 1;
SELECT * FROM t1;
Kết quả:
+------+------+------+------+ | id | c1 | c2 | c3 | |------+------+------+------| | 1 | 1 | 1 | 3 | +------+------+------+------+
Một lần nữa, c3
cột được tăng dần.
Tuy nhiên, bây giờ hãy thử cập nhật c2
cột:
UPDATE t1
SET c2 = c2 + 1
WHERE id = 1;
SELECT * FROM t1;
Kết quả:
+------+------+------+------+ | id | c1 | c2 | c3 | |------+------+------+------| | 1 | 1 | 1 | 3 | +------+------+------+------+
Không có gì thay đổi. c3
cột vẫn giữ nguyên.
Thậm chí không phải là c2
cột được cập nhật. Điều này là do, trình kích hoạt vẫn chạy thay vì câu lệnh kích hoạt.
Chạy trình kích hoạt thay vì XÓA
Chúng tôi có thể sửa đổi trình kích hoạt để chạy thay vì bất kỳ DELETE
nào tuyên bố.
ALTER TRIGGER trg_t1
ON t1
INSTEAD OF DELETE
AS
UPDATE t1
SET c3 = c3 + 1
WHERE id IN (SELECT DISTINCT id FROM deleted);
Bây giờ, hãy thử xóa tất cả các hàng và sau đó chọn tất cả các hàng từ bảng.
DELETE FROM t1;
SELECT * FROM t1;
Kết quả:
+------+------+------+------+ | id | c1 | c2 | c3 | |------+------+------+------| | 1 | 1 | 1 | 4 | +------+------+------+------+
Lưu ý rằng để trình kích hoạt này hoạt động bình thường, tôi phải truy vấn deleted
trong trình kích hoạt của tôi (trái ngược với inserted
trong các ví dụ trước).
Hai bảng này được tạo và quản lý bởi SQL Server.
deleted
bảng lưu trữ bản sao của các hàng bị ảnh hưởng trong khi DELETE
và UPDATE
các câu lệnh. Trong khi thực hiện DELETE
hoặc UPDATE
câu lệnh, các hàng bị xóa khỏi bảng trình kích hoạt và được chuyển sang bảng đã xóa.
inserted
bảng lưu trữ bản sao của các hàng bị ảnh hưởng trong khi INSERT
và UPDATE
các câu lệnh. Trong một giao dịch chèn hoặc cập nhật, các hàng mới được thêm vào cả bảng đã chèn và bảng kích hoạt. Các hàng trong bảng được chèn là bản sao của các hàng mới trong bảng trình kích hoạt.
Một số hạn chế cần lưu ý
Bạn có thể xác định tối đa một INSTEAD OF
kích hoạt mỗi INSERT
, UPDATE
hoặc DELETE
trên bảng hoặc dạng xem.
Bạn không thể xác định INSTEAD OF
kích hoạt trên các chế độ xem có thể cập nhật sử dụng WITH CHECK OPTION
.