آموزش Trigger در SQL Server: انواع، جدولهای inserted و deleted و مثال
Trigger کدی است که به یک جدول چسبیده است و با هر INSERT، UPDATE یا DELETE خودکار اجرا میشود. کاربرد معمول آن ثبت لاگ تغییرات (Audit)، اعمال قواعدی که با قیدهای ساده بیان نمیشوند و همگامسازی جدولهاست. در این مقاله انواع آن را با مثال میبینیم.
انواع Trigger
| نوع | زمان اجرا | کاربرد |
|---|---|---|
AFTER (یا FOR) | بعد از انجام عملیات و بررسی قیدها | لاگ تغییرات، بهروزرسانی جدولهای وابسته |
INSTEAD OF | بهجای عملیات اصلی | کنترل کامل؛ مثلاً حذف منطقی بهجای حذف واقعی، یا ویرایش View |
| DDL Trigger | هنگام CREATE/ALTER/DROP | جلوگیری از حذف جدول، ثبت تغییرات ساختاری |
جدولهای مجازی inserted و deleted
داخل Trigger دو جدول موقت وجود دارد که ساختار آنها شبیه جدول اصلی است:
| عملیات | inserted | deleted |
|---|---|---|
| INSERT | ردیفهای جدید | خالی |
| DELETE | خالی | ردیفهای حذفشده |
| UPDATE | مقدارهای جدید | مقدارهای قدیمی |
inserted و deleted کار کن، نه با یک متغیر تکی.مثال ۱: ثبت لاگ تغییر حقوق (AFTER UPDATE)
CREATE TABLE Employee ( EmployeeId INT PRIMARY KEY, FullName NVARCHAR(100), Salary DECIMAL(12,2) ); CREATE TABLE SalaryLog ( LogId INT IDENTITY PRIMARY KEY, EmployeeId INT, OldSalary DECIMAL(12,2), NewSalary DECIMAL(12,2), ChangedBy SYSNAME DEFAULT SUSER_SNAME(), ChangedAt DATETIME2 DEFAULT SYSDATETIME() ); GO CREATE TRIGGER trg_Employee_SalaryAudit ON Employee AFTER UPDATE AS BEGIN SET NOCOUNT ON; IF UPDATE(Salary) INSERT INTO SalaryLog (EmployeeId, OldSalary, NewSalary) SELECT d.EmployeeId, d.Salary, i.Salary FROM deleted d JOIN inserted i ON i.EmployeeId = d.EmployeeId WHERE ISNULL(d.Salary, -1) <> ISNULL(i.Salary, -1); END; GO UPDATE Employee SET Salary = 1500 WHERE EmployeeId = 1; SELECT * FROM SalaryLog;
IF UPDATE(Salary) بررسی میکند ستون حقوق در دستور آمده باشد و شرط WHERE فقط ردیفهایی را لاگ میکند که مقدارشان واقعاً عوض شده.
مثال ۲: جلوگیری از حذف (AFTER DELETE با ROLLBACK)
CREATE TRIGGER trg_Employee_NoDeleteManager ON Employee AFTER DELETE AS BEGIN IF EXISTS (SELECT 1 FROM deleted WHERE FullName = N'Admin') BEGIN ROLLBACK TRANSACTION; THROW 50010, N'حذف کاربر Admin مجاز نیست', 1; END END;
مثال ۳: حذف منطقی با INSTEAD OF
بهجای حذف واقعی، ستون IsDeleted را ۱ میکنیم تا داده برای ممیزی بماند:
CREATE TRIGGER trg_Customer_SoftDelete ON Customer INSTEAD OF DELETE AS BEGIN SET NOCOUNT ON; UPDATE c SET IsDeleted = 1 FROM Customer c JOIN deleted d ON d.CustomerId = c.CustomerId; END;
مدیریت Trigger
DISABLE TRIGGER trg_Employee_SalaryAudit ON Employee; -- غیرفعال موقت ENABLE TRIGGER trg_Employee_SalaryAudit ON Employee; DROP TRIGGER IF EXISTS trg_Employee_SalaryAudit; -- فهرست Triggerهای یک جدول SELECT name, is_disabled FROM sys.triggers WHERE parent_id = OBJECT_ID('Employee');
مشکلات رایج
- فرض یکردیفی: نوشتن
SELECT @id = EmployeeId FROM insertedبا دستور چندردیفی نتیجهی اشتباه میدهد. - Triggerهای تودرتو و بازگشتی: Triggerی که جدول دیگر را تغییر میدهد و آن جدول هم Trigger دارد، عیبیابی را سخت میکند.
- منطق سنگین: هر ثانیهی اجرای Trigger جزو زمان تراکنش اصلی است و قفلها را بیشتر نگه میدارد.
- فراموششدن: Trigger «جادویی» است و برنامهنویس بعدی ممکن است از وجودش بیخبر باشد؛ مستندسازی کن.
CHECK استفاده کن، نه Trigger. Trigger را برای ممیزی و منطق چندجدولی نگه دار.برای شناخت بیشتر اشیاء برنامهنویسی، مقالهی تفاوت Procedure، Function و View را بخوان.
سوالات متداول دربارهی این موضوع
Trigger چه زمانی اجرا میشود؟
بهطور خودکار هنگام INSERT، UPDATE یا DELETE روی جدول (DML Trigger) یا هنگام تغییر ساختار پایگاهداده (DDL Trigger)؛ نیازی به فراخوانی دستی ندارد.
جدولهای inserted و deleted چه هستند؟
جدولهای مجازی موقت داخل Trigger هستند: inserted ردیفهای جدید (بعد از تغییر) و deleted ردیفهای قدیمی (قبل از تغییر) را نگه میدارند. در UPDATE هر دو پر هستند.
آیا Trigger برای کارایی بد است؟
اگر ساده و کوتاه نوشته شود مشکلی ندارد، اما منطق سنگین یا تودرتو در Trigger عملیات نوشتن را کند و عیبیابی را سخت میکند. Trigger باید برای ممیزی و قواعدی که با قید قابل بیان نیستند استفاده شود.
میخوای SQL را از پایه و با تمرین یاد بگیری؟
دورهی رایگان SQLFarsi را با Playground و پروژههای واقعی دنبال کن.
شروع یادگیری