آموزش دستور CREATE TRIGGER در SQL Server
مقدمه
CREATE TRIGGER یکی از اجزای مهم مدیریت Trigger در Microsoft SQL Server است. این قابلیت زمانی ارزشمند میشود که واکنش به تغییر داده یا ساختار باید در سطح موتور پایگاه داده یکسان و قابل ممیزی باشد. با این حال هر تریگر بخشی از تراکنش فراخوان است؛ بنابراین خطا، تأخیر یا قفل اضافه آن مستقیماً روی عملیات اصلی اثر میگذارد.
در این راهنما از تعریف پایه تا سناریوهای چندردیفی، NULL، کنترل خطا، ممیزی، امنیت و بهینهسازی پیش میرویم. همه نمونهها برای محیط آموزشی نوشته شدهاند و اشیای موقت آموزشی را در پایان پاک میکنند. برای دیدن جایگاه این موضوع میان سایر انواع و دستورها، راهنمای جامع Triggerهای SQL Server را نیز مطالعه کنید.
تعریف، نحو و دامنه کاربرد
ساخت و تعریف تریگر جدید هدف اصلی این مبحث است. تعریف دقیق باید شامل رویداد، دامنه شیء، زمان اجرا و رفتار تراکنشی باشد. در تریگرهای DML دو جدول منطقی inserted و deleted تصویر مجموعه ردیفهای جدید و قدیم را ارائه میکنند؛ در تریگرهای DDL تابع EVENTDATA جزئیات رخداد ساختاری را به XML برمیگرداند؛ و در LOGON باید مسیر بازیابی مدیریتی از قبل تضمین شود.
الگوی نحوی مرجع
-- الگوی آموزشی؛ نام، دامنه و رویداد را متناسب با موضوع انتخاب کنید
CREATE TRIGGER dbo.TriggerName ON dbo.TableName AFTER INSERT
AS
BEGIN
SET NOCOUNT ON;
-- منطق مجموعهمحور، کوتاه و قابل آزمون
END;
ورودیها و خروجی
- نام تریگر باید در دامنه مربوط یکتا، معنادار و مطابق استاندارد تیم باشد.
- رویداد یا گروه رویداد تعیین میکند تریگر در چه تغییراتی اجرا شود.
- خروجی مستقیمی مانند تابع وجود ندارد؛ اثر تریگر در تراکنش، داده ممیزی، پیام خطا یا ROLLBACK دیده میشود.
- مجوز ایجاد یا تغییر تریگر باید فقط به نقش استقرار داده شود و حساب برنامه مجوز مدیریتی نداشته باشد.
مثالهای عملی از پایه تا حرفهای
مثال 1: ساختار پایه و اجرای نخستین سناریو
این مثال از یک سناریوی کوچک و قابل مشاهده شروع میکند تا ترتیب اجرای دستور، رویداد و اثر نهایی روشن شود. تمرکز این Query روی CREATE TRIGGER است و نام اشیای آزمایشی با پیشوند G17 انتخاب شده تا پاکسازی و تشخیص آنها ساده باشد.
DROP TABLE IF EXISTS dbo.G17_Create_Audit, dbo.G17_Create_Orders;
CREATE TABLE dbo.G17_Create_Orders(OrderID int PRIMARY KEY, Amount decimal(12,2));
CREATE TABLE dbo.G17_Create_Audit(AuditID int IDENTITY PRIMARY KEY, OrderID int, EventName nvarchar(20));
EXEC(N'CREATE TRIGGER dbo.TR_G17_Create_Insert ON dbo.G17_Create_Orders AFTER INSERT AS BEGIN SET NOCOUNT ON; INSERT dbo.G17_Create_Audit(OrderID,EventName) SELECT OrderID,N''INSERT'' FROM inserted; END');
INSERT dbo.G17_Create_Orders VALUES(1,125000);
SELECT * FROM dbo.G17_Create_Audit;
DROP TRIGGER dbo.TR_G17_Create_Insert;
DROP TABLE dbo.G17_Create_Audit, dbo.G17_Create_Orders;
| خروجی مورد انتظار | تفسیر |
|---|
| نتیجه نمونه 1 | دستور مرتبط با CREATE TRIGGER اجرا شده و نتیجه قابل کنترل است. |
نکته کاربردی: این الگو را پیش از انتقال به تولید با عملیات چندردیفی، مقدار NULL و خطای عمدی آزمایش کنید. در سناریوی واقعی باید دسترسیها حداقلی، نام اشیا ثابت، تراکنش کوتاه و جدول مقصد دارای ایندکس مناسب باشد؛ همچنین ثبت رخداد نباید اطلاعات حساس غیرضروری را ذخیره کند.
مثال 2: ثبت ممیزی روی جدول عملیاتی
در این سناریو تغییرات یک جدول کسبوکار در جدول ممیزی ذخیره میشود تا زمان، کاربر و نوع عملیات قابل پیگیری باشد. تمرکز این Query روی CREATE TRIGGER است و نام اشیای آزمایشی با پیشوند G17 انتخاب شده تا پاکسازی و تشخیص آنها ساده باشد.
DROP TABLE IF EXISTS dbo.G17_Create_Log, dbo.G17_Create_Product;
CREATE TABLE dbo.G17_Create_Product(ProductID int PRIMARY KEY, Price decimal(12,2));
CREATE TABLE dbo.G17_Create_Log(ProductID int, OldPrice decimal(12,2), NewPrice decimal(12,2), ChangedAt datetime2);
EXEC(N'CREATE TRIGGER dbo.TR_G17_Create_Price ON dbo.G17_Create_Product AFTER UPDATE AS BEGIN SET NOCOUNT ON; INSERT dbo.G17_Create_Log SELECT d.ProductID,d.Price,i.Price,SYSDATETIME() FROM inserted i JOIN deleted d ON d.ProductID=i.ProductID WHERE i.Price<>d.Price; END');
INSERT dbo.G17_Create_Product VALUES(1,90);
UPDATE dbo.G17_Create_Product SET Price=110 WHERE ProductID=1;
SELECT ProductID,OldPrice,NewPrice FROM dbo.G17_Create_Log;
DROP TRIGGER dbo.TR_G17_Create_Price;
DROP TABLE dbo.G17_Create_Log, dbo.G17_Create_Product;
| خروجی مورد انتظار | تفسیر |
|---|
| نتیجه نمونه 2 | دستور مرتبط با CREATE TRIGGER اجرا شده و نتیجه قابل کنترل است. |
نکته کاربردی: این الگو را پیش از انتقال به تولید با عملیات چندردیفی، مقدار NULL و خطای عمدی آزمایش کنید. در سناریوی واقعی باید دسترسیها حداقلی، نام اشیا ثابت، تراکنش کوتاه و جدول مقصد دارای ایندکس مناسب باشد؛ همچنین ثبت رخداد نباید اطلاعات حساس غیرضروری را ذخیره کند.
مثال 3: پردازش چندردیفی و مجموعهمحور
هدف این مثال نشاندادن این نکته است که inserted و deleted ممکن است همزمان چند ردیف داشته باشند و منطق نباید تکردیفی نوشته شود. تمرکز این Query روی CREATE TRIGGER است و نام اشیای آزمایشی با پیشوند G17 انتخاب شده تا پاکسازی و تشخیص آنها ساده باشد.
DROP TABLE IF EXISTS dbo.G17_Create_BatchLog, dbo.G17_Create_Batch;
CREATE TABLE dbo.G17_Create_Batch(ID int PRIMARY KEY, Qty int);
CREATE TABLE dbo.G17_Create_BatchLog(ID int, Qty int);
EXEC(N'CREATE TRIGGER dbo.TR_G17_Create_Batch ON dbo.G17_Create_Batch AFTER INSERT AS BEGIN SET NOCOUNT ON; INSERT dbo.G17_Create_BatchLog SELECT ID,Qty FROM inserted; END');
INSERT dbo.G17_Create_Batch VALUES(1,2),(2,4),(3,6);
SELECT COUNT(*) AS LoggedRows FROM dbo.G17_Create_BatchLog;
DROP TRIGGER dbo.TR_G17_Create_Batch;
DROP TABLE dbo.G17_Create_BatchLog, dbo.G17_Create_Batch;
| خروجی مورد انتظار | تفسیر |
|---|
| نتیجه نمونه 3 | دستور مرتبط با CREATE TRIGGER اجرا شده و نتیجه قابل کنترل است. |
نکته کاربردی: این الگو را پیش از انتقال به تولید با عملیات چندردیفی، مقدار NULL و خطای عمدی آزمایش کنید. در سناریوی واقعی باید دسترسیها حداقلی، نام اشیا ثابت، تراکنش کوتاه و جدول مقصد دارای ایندکس مناسب باشد؛ همچنین ثبت رخداد نباید اطلاعات حساس غیرضروری را ذخیره کند.
مثال 4: استفاده در مسیر UPDATE
این نمونه رفتار موضوع را هنگام بهروزرسانی بررسی میکند و تفاوت مقدار قدیم و جدید را بدون اتکا به متغیر اسکالر نشان میدهد. تمرکز این Query روی CREATE TRIGGER است و نام اشیای آزمایشی با پیشوند G17 انتخاب شده تا پاکسازی و تشخیص آنها ساده باشد.
DROP TABLE IF EXISTS dbo.G17_Create_UpdateLog, dbo.G17_Create_Customer;
CREATE TABLE dbo.G17_Create_Customer(ID int PRIMARY KEY, Credit int);
CREATE TABLE dbo.G17_Create_UpdateLog(ID int, Delta int);
EXEC(N'CREATE TRIGGER dbo.TR_G17_Create_Credit ON dbo.G17_Create_Customer AFTER UPDATE AS BEGIN SET NOCOUNT ON; INSERT dbo.G17_Create_UpdateLog SELECT i.ID,i.Credit-d.Credit FROM inserted i JOIN deleted d ON i.ID=d.ID; END');
INSERT dbo.G17_Create_Customer VALUES(1,100);
UPDATE dbo.G17_Create_Customer SET Credit=135 WHERE ID=1;
SELECT * FROM dbo.G17_Create_UpdateLog;
DROP TRIGGER dbo.TR_G17_Create_Credit;
DROP TABLE dbo.G17_Create_UpdateLog, dbo.G17_Create_Customer;
| خروجی مورد انتظار | تفسیر |
|---|
| نتیجه نمونه 4 | دستور مرتبط با CREATE TRIGGER اجرا شده و نتیجه قابل کنترل است. |
نکته کاربردی: این الگو را پیش از انتقال به تولید با عملیات چندردیفی، مقدار NULL و خطای عمدی آزمایش کنید. در سناریوی واقعی باید دسترسیها حداقلی، نام اشیا ثابت، تراکنش کوتاه و جدول مقصد دارای ایندکس مناسب باشد؛ همچنین ثبت رخداد نباید اطلاعات حساس غیرضروری را ذخیره کند.
مثال 5: اعمال شرط تجاری و کنترل تراکنش
سناریو یک قانون کسبوکار را در مرز پایگاه داده اعمال میکند و نحوه بازگردانی تغییر نامعتبر را بهشکل شفاف نمایش میدهد. تمرکز این Query روی CREATE TRIGGER است و نام اشیای آزمایشی با پیشوند G17 انتخاب شده تا پاکسازی و تشخیص آنها ساده باشد.
DROP TABLE IF EXISTS dbo.G17_Create_Invoice;
CREATE TABLE dbo.G17_Create_Invoice(ID int PRIMARY KEY, Amount decimal(12,2));
EXEC(N'CREATE TRIGGER dbo.TR_G17_Create_InvoiceRule ON dbo.G17_Create_Invoice AFTER INSERT,UPDATE AS BEGIN SET NOCOUNT ON; IF EXISTS(SELECT 1 FROM inserted WHERE Amount<0) THROW 51000,N''مبلغ منفی مجاز نیست.'',1; END');
BEGIN TRY INSERT dbo.G17_Create_Invoice VALUES(1,-10); END TRY BEGIN CATCH SELECT ERROR_MESSAGE() AS ValidationMessage; END CATCH;
DROP TRIGGER dbo.TR_G17_Create_InvoiceRule;
DROP TABLE dbo.G17_Create_Invoice;
| خروجی مورد انتظار | تفسیر |
|---|
| نتیجه نمونه 5 | دستور مرتبط با CREATE TRIGGER اجرا شده و نتیجه قابل کنترل است. |
نکته کاربردی: این الگو را پیش از انتقال به تولید با عملیات چندردیفی، مقدار NULL و خطای عمدی آزمایش کنید. در سناریوی واقعی باید دسترسیها حداقلی، نام اشیا ثابت، تراکنش کوتاه و جدول مقصد دارای ایندکس مناسب باشد؛ همچنین ثبت رخداد نباید اطلاعات حساس غیرضروری را ذخیره کند.
مثال 6: رفتار مقدار NULL و داده ناقص
در این مثال حالت NULL عمداً وارد جریان میشود تا مقایسه سهارزشی SQL و استفاده درست از COALESCE یا شرط IS NULL دیده شود. تمرکز این Query روی CREATE TRIGGER است و نام اشیای آزمایشی با پیشوند G17 انتخاب شده تا پاکسازی و تشخیص آنها ساده باشد.
DROP TABLE IF EXISTS dbo.G17_Create_NullLog, dbo.G17_Create_Person;
CREATE TABLE dbo.G17_Create_Person(ID int PRIMARY KEY, Email nvarchar(100) NULL);
CREATE TABLE dbo.G17_Create_NullLog(ID int, StatusText nvarchar(20));
EXEC(N'CREATE TRIGGER dbo.TR_G17_Create_Null ON dbo.G17_Create_Person AFTER INSERT AS BEGIN SET NOCOUNT ON; INSERT dbo.G17_Create_NullLog SELECT ID,CASE WHEN Email IS NULL THEN N''بدون ایمیل'' ELSE N''دارای ایمیل'' END FROM inserted; END');
INSERT dbo.G17_Create_Person VALUES(1,NULL),(2,N'a@b.test');
SELECT * FROM dbo.G17_Create_NullLog ORDER BY ID;
DROP TRIGGER dbo.TR_G17_Create_Null;
DROP TABLE dbo.G17_Create_NullLog, dbo.G17_Create_Person;
| خروجی مورد انتظار | تفسیر |
|---|
| نتیجه نمونه 6 | دستور مرتبط با CREATE TRIGGER اجرا شده و نتیجه قابل کنترل است. |
نکته کاربردی: این الگو را پیش از انتقال به تولید با عملیات چندردیفی، مقدار NULL و خطای عمدی آزمایش کنید. در سناریوی واقعی باید دسترسیها حداقلی، نام اشیا ثابت، تراکنش کوتاه و جدول مقصد دارای ایندکس مناسب باشد؛ همچنین ثبت رخداد نباید اطلاعات حساس غیرضروری را ذخیره کند.
مثال 7: حالت مرزی و عملیات دستهای
این نمونه یک ورودی غیرمعمول و چند ردیف همزمان را آزمایش میکند تا پایداری منطق در بار واقعی ارزیابی شود. تمرکز این Query روی CREATE TRIGGER است و نام اشیای آزمایشی با پیشوند G17 انتخاب شده تا پاکسازی و تشخیص آنها ساده باشد.
DROP TABLE IF EXISTS dbo.G17_Create_EdgeLog, dbo.G17_Create_Edge;
CREATE TABLE dbo.G17_Create_Edge(ID int PRIMARY KEY, ValueText nvarchar(50));
CREATE TABLE dbo.G17_Create_EdgeLog(RowCountValue int);
EXEC(N'CREATE TRIGGER dbo.TR_G17_Create_Edge ON dbo.G17_Create_Edge AFTER INSERT AS BEGIN SET NOCOUNT ON; INSERT dbo.G17_Create_EdgeLog VALUES((SELECT COUNT(*) FROM inserted)); END');
INSERT dbo.G17_Create_Edge VALUES(1,N''الف''),(2,N''''),(3,NULL);
SELECT * FROM dbo.G17_Create_EdgeLog;
DROP TRIGGER dbo.TR_G17_Create_Edge;
DROP TABLE dbo.G17_Create_EdgeLog, dbo.G17_Create_Edge;
| خروجی مورد انتظار | تفسیر |
|---|
| نتیجه نمونه 7 | دستور مرتبط با CREATE TRIGGER اجرا شده و نتیجه قابل کنترل است. |
نکته کاربردی: این الگو را پیش از انتقال به تولید با عملیات چندردیفی، مقدار NULL و خطای عمدی آزمایش کنید. در سناریوی واقعی باید دسترسیها حداقلی، نام اشیا ثابت، تراکنش کوتاه و جدول مقصد دارای ایندکس مناسب باشد؛ همچنین ثبت رخداد نباید اطلاعات حساس غیرضروری را ذخیره کند.
مثال 8: گزارشگیری سازمانی و ردیابی رخداد
سناریو برای تیم عملیات و امنیت طراحی شده است و اطلاعاتی تولید میکند که در گزارش رخداد و تحلیل تغییرات قابل استفاده باشد. تمرکز این Query روی CREATE TRIGGER است و نام اشیای آزمایشی با پیشوند G17 انتخاب شده تا پاکسازی و تشخیص آنها ساده باشد.
DROP TABLE IF EXISTS dbo.G17_Create_EventLog, dbo.G17_Create_Asset;
CREATE TABLE dbo.G17_Create_Asset(ID int PRIMARY KEY, StateCode tinyint);
CREATE TABLE dbo.G17_Create_EventLog(ID int, LoginName sysname, EventAt datetime2);
EXEC(N'CREATE TRIGGER dbo.TR_G17_Create_Event ON dbo.G17_Create_Asset AFTER UPDATE AS BEGIN SET NOCOUNT ON; INSERT dbo.G17_Create_EventLog SELECT i.ID,ORIGINAL_LOGIN(),SYSUTCDATETIME() FROM inserted i JOIN deleted d ON i.ID=d.ID WHERE i.StateCode<>d.StateCode; END');
INSERT dbo.G17_Create_Asset VALUES(1,1);
UPDATE dbo.G17_Create_Asset SET StateCode=2 WHERE ID=1;
SELECT ID,LoginName FROM dbo.G17_Create_EventLog;
DROP TRIGGER dbo.TR_G17_Create_Event;
DROP TABLE dbo.G17_Create_EventLog, dbo.G17_Create_Asset;
| خروجی مورد انتظار | تفسیر |
|---|
| نتیجه نمونه 8 | دستور مرتبط با CREATE TRIGGER اجرا شده و نتیجه قابل کنترل است. |
نکته کاربردی: این الگو را پیش از انتقال به تولید با عملیات چندردیفی، مقدار NULL و خطای عمدی آزمایش کنید. در سناریوی واقعی باید دسترسیها حداقلی، نام اشیا ثابت، تراکنش کوتاه و جدول مقصد دارای ایندکس مناسب باشد؛ همچنین ثبت رخداد نباید اطلاعات حساس غیرضروری را ذخیره کند.
مثال 9: روش اشتباه و نسخه اصلاحشده
ابتدا الگوی پرخطر معرفی و سپس نسخه مجموعهمحور، قابل نگهداری و سازگار با تراکنش جایگزین میشود. تمرکز این Query روی CREATE TRIGGER است و نام اشیای آزمایشی با پیشوند G17 انتخاب شده تا پاکسازی و تشخیص آنها ساده باشد.
DROP TABLE IF EXISTS dbo.G17_Create_SetLog, dbo.G17_Create_Set;
CREATE TABLE dbo.G17_Create_Set(ID int PRIMARY KEY, Qty int);
CREATE TABLE dbo.G17_Create_SetLog(ID int, Qty int);
EXEC(N'CREATE TRIGGER dbo.TR_G17_Create_Set ON dbo.G17_Create_Set AFTER INSERT AS BEGIN SET NOCOUNT ON; INSERT dbo.G17_Create_SetLog SELECT ID,Qty FROM inserted; END');
INSERT dbo.G17_Create_Set VALUES(1,10),(2,20);
SELECT SUM(Qty) AS LoggedQty FROM dbo.G17_Create_SetLog;
DROP TRIGGER dbo.TR_G17_Create_Set;
DROP TABLE dbo.G17_Create_SetLog, dbo.G17_Create_Set;
| خروجی مورد انتظار | تفسیر |
|---|
| نسخه اصلاحشده اجرا شد | دستور مرتبط با CREATE TRIGGER اجرا شده و نتیجه قابل کنترل است. |
نکته کاربردی: این الگو را پیش از انتقال به تولید با عملیات چندردیفی، مقدار NULL و خطای عمدی آزمایش کنید. در سناریوی واقعی باید دسترسیها حداقلی، نام اشیا ثابت، تراکنش کوتاه و جدول مقصد دارای ایندکس مناسب باشد؛ همچنین ثبت رخداد نباید اطلاعات حساس غیرضروری را ذخیره کند.
مثال 10: کارایی، ایندکس و کاهش سربار
مثال پایانی روی کاهش خواندن منطقی، کوتاه نگهداشتن تراکنش و ایندکس مناسب ستونهای اتصال و فیلتر تمرکز دارد. تمرکز این Query روی CREATE TRIGGER است و نام اشیای آزمایشی با پیشوند G17 انتخاب شده تا پاکسازی و تشخیص آنها ساده باشد.
DROP TABLE IF EXISTS dbo.G17_Create_PerfLog, dbo.G17_Create_Perf;
CREATE TABLE dbo.G17_Create_Perf(ID int PRIMARY KEY, StatusCode tinyint);
CREATE TABLE dbo.G17_Create_PerfLog(ID int PRIMARY KEY, StatusCode tinyint);
CREATE INDEX IX_G17_Create_Perf_Status ON dbo.G17_Create_Perf(StatusCode);
EXEC(N'CREATE TRIGGER dbo.TR_G17_Create_Perf ON dbo.G17_Create_Perf AFTER INSERT AS BEGIN SET NOCOUNT ON; INSERT dbo.G17_Create_PerfLog(ID,StatusCode) SELECT ID,StatusCode FROM inserted; END');
INSERT dbo.G17_Create_Perf VALUES(1,1),(2,2),(3,1);
SELECT ID FROM dbo.G17_Create_Perf WHERE StatusCode=1;
DROP TRIGGER dbo.TR_G17_Create_Perf;
DROP TABLE dbo.G17_Create_PerfLog, dbo.G17_Create_Perf;
| خروجی مورد انتظار | تفسیر |
|---|
| سربار کنترلشده و خروجی صحیح | دستور مرتبط با CREATE TRIGGER اجرا شده و نتیجه قابل کنترل است. |
نکته کاربردی: این الگو را پیش از انتقال به تولید با عملیات چندردیفی، مقدار NULL و خطای عمدی آزمایش کنید. در سناریوی واقعی باید دسترسیها حداقلی، نام اشیا ثابت، تراکنش کوتاه و جدول مقصد دارای ایندکس مناسب باشد؛ همچنین ثبت رخداد نباید اطلاعات حساس غیرضروری را ذخیره کند.
خطاهای رایج و روش عیبیابی
مهمترین خطا در CREATE TRIGGER نوشتن SELECT اسکالر از inserted یا deleted و فرض وجود تنها یک ردیف است. خطای دوم انجام پردازش کند، Cursor، تماس بیرونی یا Query بدون ایندکس درون تراکنش است. خطای سوم فراموشکردن اثر بازگشتی یا زنجیرهای Triggerهاست که میتواند ترتیب رخدادها را پیچیده کند.
برای عیبیابی، ابتدا تعریف را از sys.sql_modules و وضعیت را از sys.triggers استخراج کنید. سپس با Extended Events، Query Store در بخشهای قابل ثبت، آمار IO و TIME و گزارش قفلها مشخص کنید تأخیر داخل کدام عبارت رخ میدهد. آزمون باید عملیات صفرردیفی، تکردیفی، دستهای، خطادار و همزمان را پوشش دهد و نتیجه تراکنش اصلی را نیز کنترل کند.
ملاحظات کارایی و امنیت
تریگر سریع الزاماً تریگر کوتاهمتن نیست؛ معیار واقعی تعداد خواندن منطقی، طرح اجرا، مدت نگهداری قفل و رشد Log است. اتصال inserted یا deleted به جدولهای بزرگ باید از ستون ایندکسشده انجام شود. ثبت فقط ستونهای لازم، استفاده از INSERT مجموعهمحور و حذف Queryهای تکراری معمولاً بیشترین بهبود را ایجاد میکند.
از دید امنیتی، EXECUTE AS، مالکیت زنجیرهای و دسترسی مقصد ممیزی باید بررسی شود. متن EVENTDATA یا داده برنامه ممکن است شامل اطلاعات حساس باشد؛ بنابراین حداقلگرایی، محدودیت دسترسی و سیاست نگهداری لازم است. برای LOGON هرگز بدون اتصال DAC، استثنای حساب اضطراری و آزمون جداگانه محدودیت سراسری فعال نکنید.
سؤالات متداول
پرسش 1: CREATE TRIGGER دقیقاً چه مسئلهای را حل میکند؟
این موضوع اجرای خودکار یا مدیریت منطق واکنشی را نزدیک داده ممکن میکند. انتخاب آن باید پس از بررسی جایگزینهایی مانند قید، رویه ذخیرهشده، Extended Events و لایه سرویس انجام شود تا پیچیدگی پنهان ایجاد نشود.
پرسش 2: برای شروع یادگیری CREATE TRIGGER چه پیشنیازهایی لازم است؟
شناخت تراکنش، سطوح دسترسی، دستورهای DML و DDL و شیوه کار جداول منطقی inserted و deleted پایه مناسبی است. تمرین روی پایگاه آزمایشی و مشاهده execution plan و آمار زمان اجرا مسیر یادگیری را بسیار کوتاهتر میکند.
پرسش 3: آیا استفاده از CREATE TRIGGER برای یک پروژه تجاری مناسب است؟
بله، وقتی الزام ممیزی یا قانون یکپارچگی باید مستقل از برنامههای متعدد اجرا شود انتخاب خوبی است. در پروژه تجاری لازم است هزینه نگهداری، مانیتورینگ، آزمون بار و روش غیرفعالسازی اضطراری نیز در برآورد فنی دیده شود.
پرسش 4: هزینه طراحی و پیادهسازی حرفهای CREATE TRIGGER چگونه تعیین میشود؟
حجم تراکنش، تعداد جدولها، حساسیت امنیتی، نیاز گزارشگیری و سطح آزمون عوامل اصلی هستند. پیش از برآورد، مشاوره SQL Server باید سناریوهای شکست، همزمانی و بازیابی را استخراج کند تا دامنه کار دقیق باشد.
پرسش 5: CREATE TRIGGER چه تفاوتی با اجرای همان منطق در برنامه دارد؟
منطق تریگر برای همه مصرفکنندگان داده یکسان اجرا میشود، اما در برنامه مشاهدهپذیری و کنترل جریان سادهتر است. تصمیم درست معمولاً ترکیبی است: قواعد حیاتی نزدیک داده و گردشکارهای طولانی در سرویس برنامه قرار میگیرند.
پرسش 6: برای بازبینی یا اصلاح CREATE TRIGGER موجود چه خدمتی لازم است؟
بازبینی شامل استخراج تعریف، تحلیل وابستگی، اندازهگیری زمان و خواندن منطقی، بررسی بنبست و ساخت آزمون چندردیفی است. سپس تغییر در محیط آزمایش اجرا و با اسکریپت بازگشت و چکلیست استقرار تحویل میشود.
پرسش 7: رایجترین خطا در CREATE TRIGGER چیست؟
فرض تکردیفی بودن inserted یا deleted، حذف SET NOCOUNT ON و اجرای Query سنگین برای هر ردیف از خطاهای پرتکرار هستند. راهحل، منطق مجموعهمحور، تراکنش کوتاه، مدیریت خطا و تست INSERT یا UPDATE دستهای است.
پرسش 8: CREATE TRIGGER چه اثری بر Performance دارد؟
زمان اجرای تریگر بخشی از زمان همان تراکنش است و قفلها را طولانیتر نگه میدارد. ایندکس ستونهای اتصال، محدودکردن ستونهای ثبتشده، پرهیز از فراخوانی شبکه و پایش Query Store یا Extended Events ضروری است.
پرسش 9: بهترین روش نگهداری CREATE TRIGGER چیست؟
تعریف شیء باید در کنترل نسخه باشد و همراه با آزمون مثبت، منفی، NULL، چندردیفی و همزمانی منتشر شود. نامگذاری استاندارد، توضیح هدف، مالک مشخص و اسکریپت Rollback باعث میشود تغییرات بعدی قابل اعتماد بماند.
پرسش 10: CREATE TRIGGER با کدام نسخههای SQL Server سازگار است؟
هسته قابلیت در نسخههای متداول SQL Server وجود دارد، ولی گزینههایی مانند CREATE OR ALTER یا برخی رویدادها به نسخه وابستهاند. پیش از استقرار باید مستندات همان نسخه، Compatibility Level و محدودیت Azure SQL بررسی شود.
سؤالات مصاحبه تخصصی
سؤال 1: چرا یک تریگر باید مجموعهمحور باشد؟
زیرا یک دستور میتواند صفر، یک یا هزاران ردیف را تغییر دهد و inserted یا deleted نماینده کل مجموعه است، نه یک ردیف تضمینشده.
سؤال 2: SET NOCOUNT ON چه فایدهای دارد؟
پیام تعداد ردیفهای میانی را حذف میکند و از ایجاد ترافیک و رفتار غیرمنتظره برخی کلاینتها جلوگیری میکند.
سؤال 3: چگونه اثر کارایی را اندازه میگیرید؟
مدت تراکنش، CPU، logical reads، waitها، قفلها و برنامه اجرای Queryهای داخل تریگر پیش و پس از تغییر مقایسه میشوند.
سؤال 4: چه زمانی تریگر انتخاب مناسبی نیست؟
وقتی پردازش طولانی، تماس شبکه، ارسال ایمیل یا گردشکار قابل تکرار لازم است، صف یا سرویس پسزمینه انتخاب امنتری است.
سؤال 5: استقرار CREATE TRIGGER چگونه ایمن میشود؟
با نسخهگذاری، آزمون روی داده مشابه تولید، پنجره استقرار، اسکریپت بازگشت، حساب اضطراری و مانیتورینگ پس از انتشار.
چکلیست نهایی و جمعبندی
- هدف Trigger و دلیل انتخاب آن مستند شده است.
- عملیات چندردیفی، NULL، خطا و Rollback آزمایش شدهاند.
- زمان اجرا و logical reads پیش و پس از تغییر ثبت شدهاند.
- اسکریپت استقرار و بازگشت در کنترل نسخه قرار دارد.
- مانیتورینگ و مالک پاسخگو برای محیط تولید مشخص است.
CREATE TRIGGER وقتی موفق است که قانون موردنظر را بهصورت قابل پیشبینی، سریع و قابل مشاهده اجرا کند. طراحی مجموعهمحور، تراکنش کوتاه، آزمون خودکار و مسیر بازگشت چهار ستون اصلی این موفقیت هستند. برای ادامه یادگیری و مقایسه با مباحث مرتبط، به مقاله مادر تریگرها در SQL Server بازگردید.