ฉันชอบโซลูชันที่เป็น "วิทยาศาสตร์คอมพิวเตอร์ที่สง่างาม" วิธีการแก้ปัญหาของฉันที่นี่ฮิต pseudotables [แทรก] และ [ลบ] หนึ่งครั้งเพื่อรับสถานะของพวกเขาและทำให้ผลในตัวแปรบิตแมป จากนั้นแต่ละชุดค่าผสมที่เป็นไปได้ของ INSERT, UPDATE และ DELETE สามารถทดสอบได้อย่างง่ายดายตลอดทั้งทริกเกอร์ด้วยการประเมินไบนารีที่มีประสิทธิภาพ (ยกเว้นชุด INSERT หรือ DELETE ที่ไม่น่าจะเกิดขึ้น)
มันทำให้สมมติฐานที่ว่ามันไม่สำคัญว่าคำสั่ง DML คืออะไรหากไม่มีการแก้ไขแถว (ซึ่งควรจะตอบสนองต่อกรณีส่วนใหญ่) ดังนั้นแม้จะไม่สมบูรณ์เท่ากับโซลูชันของ Roman Pekar แต่ก็มีประสิทธิภาพมากกว่า
ด้วยวิธีนี้เรามีความเป็นไปได้ของทริกเกอร์ "สำหรับ INSERT, UPDATE, DELETE" หนึ่งรายการต่อหนึ่งตารางทำให้เรา A) ควบคุมลำดับการดำเนินการได้อย่างสมบูรณ์และ b) การใช้โค้ดหนึ่งรหัสต่อการกระทำที่ใช้งานได้หลายอย่าง (เห็นได้ชัดว่าทุกรูปแบบการใช้งานมีข้อดีและข้อเสียของมันคุณจะต้องประเมินระบบของคุณเป็นรายบุคคลสำหรับสิ่งที่ดีที่สุดจริงๆ)
หมายเหตุว่า "มีอยู่ (* เลือกจาก«แทรก / ถูกลบ»)" งบมีประสิทธิภาพมากเนื่องจากไม่มีการเข้าถึงดิสก์ ( https://social.msdn.microsoft.com/Forums/en-US/01744422-23fe-42f6 -9ab0-a255cdf2904a )
use tempdb
;
create table dbo.TrigAction (asdf int)
;
GO
create trigger dbo.TrigActionTrig
on dbo.TrigAction
for INSERT, UPDATE, DELETE
as
declare @Action tinyint
;
-- Create bit map in @Action using bitwise OR "|"
set @Action = (-- 1: INSERT, 2: DELETE, 3: UPDATE, 0: No Rows Modified
(select case when exists (select * from inserted) then 1 else 0 end)
| (select case when exists (select * from deleted ) then 2 else 0 end))
;
-- 21 <- Binary bit values
-- 00 -> No Rows Modified
-- 01 -> INSERT -- INSERT and UPDATE have the 1 bit set
-- 11 -> UPDATE <
-- 10 -> DELETE -- DELETE and UPDATE have the 2 bit set
raiserror(N'@Action = %d', 10, 1, @Action) with nowait
;
if (@Action = 0) raiserror(N'No Data Modified.', 10, 1) with nowait
;
-- do things for INSERT only
if (@Action = 1) raiserror(N'Only for INSERT.', 10, 1) with nowait
;
-- do things for UPDATE only
if (@Action = 3) raiserror(N'Only for UPDATE.', 10, 1) with nowait
;
-- do things for DELETE only
if (@Action = 2) raiserror(N'Only for DELETE.', 10, 1) with nowait
;
-- do things for INSERT or UPDATE
if (@Action & 1 = 1) raiserror(N'For INSERT or UPDATE.', 10, 1) with nowait
;
-- do things for UPDATE or DELETE
if (@Action & 2 = 2) raiserror(N'For UPDATE or DELETE.', 10, 1) with nowait
;
-- do things for INSERT or DELETE (unlikely)
if (@Action in (1,2)) raiserror(N'For INSERT or DELETE.', 10, 1) with nowait
-- if already "return" on @Action = 0, then use @Action < 3 for INSERT or DELETE
;
GO
set nocount on;
raiserror(N'
INSERT 0...', 10, 1) with nowait;
insert dbo.TrigAction (asdf) select top 0 object_id from sys.objects;
raiserror(N'
INSERT 3...', 10, 1) with nowait;
insert dbo.TrigAction (asdf) select top 3 object_id from sys.objects;
raiserror(N'
UPDATE 0...', 10, 1) with nowait;
update t set asdf = asdf /1 from dbo.TrigAction t where asdf <> asdf;
raiserror(N'
UPDATE 3...', 10, 1) with nowait;
update t set asdf = asdf /1 from dbo.TrigAction t;
raiserror(N'
DELETE 0...', 10, 1) with nowait;
delete t from dbo.TrigAction t where asdf < 0;
raiserror(N'
DELETE 3...', 10, 1) with nowait;
delete t from dbo.TrigAction t;
GO
drop table dbo.TrigAction
;
GO