إنشاء مشغلات

مكتمل

المحفزات هي إجراءات مخزنة خاصة يتم تنفيذها تلقائيا عند حدوث أحداث محددة في قاعدة بياناتك. أنت تحدد محفزات للحفاظ على سلامة البيانات، وتطبيق قواعد العمل، وأتمتة عمليات قاعدة البيانات دون الحاجة إلى كود على مستوى التطبيق.

فهم أساسيات الزناد

المحفز يستجيب لتعديل البيانات أو تغييرات المخطط في قاعدة بياناتك. عند إنشاء محفز، تحدد الحدث الذي يفعله والإجراءات التي يقوم بها.

المحفزات تنفذ تلقائيا. على عكس الإجراءات المخزنة التي تستدعيها صراحة، تفعل إطلاق نار استجابة لعبارات INSERT، UPDATE، DELETE، أو DL. يجعلها هذه اللعبة التلقائية قوية في تطبيق القواعد التي يجب أن تطبق بشكل متسق على جميع تعديلات البيانات.

يدعم SQL Server فئتين رئيسيتين من المشغلات: محفزات DML (لغة معالجة البيانات) ومحفزات DDL (لغة تعريف البيانات). تستجيب محفزات DML للتغيرات في بيانات الجدول، بينما تستجيب محفزات DDL لتغييرات المخطط مثل CREATE، ALTER، أو DROP العبارات.

إنشاء محفزات DML لتعديلات البيانات

تقوم مشغلات DML بمراقبة والاستجابة لتغييرات البيانات في الجداول أو العروض. تعرفها إما بعد المحفزات أو بدلا من المحفزات.

يتم تنفيذ محفزات AFTER بعد اكتمال بيان التفعيل. تقوم قاعدة البيانات أولا بتعديل البيانات، ثم تشغل كود التشغيل. تستخدم مشغلات AFTER للتحقق من التغييرات، أو تحديث الجداول ذات الصلة، أو تسجيل التعديلات:

CREATE TRIGGER tr_UpdateInventory
ON Sales.OrderDetails
AFTER INSERT
AS
BEGIN
    UPDATE Inventory.Products
    SET QuantityInStock = QuantityInStock - i.Quantity
    FROM Inventory.Products p
    INNER JOIN inserted i ON p.ProductID = i.ProductID;
END;

بدلا من ذلك، تحل محفزات OF محل بيان تعديل البيانات الأصلي. يتم تنفيذ رمز المحفز بدلا من INSERTالعملية ، UPDATE، أو DELETE . تستخدم محفزات INSTEAD OF لتعديل العروض التي عادة لا تقبل التعديلات المباشرة أو لتنفيذ منطق الأعمال المعقد:

CREATE TRIGGER tr_UpdateOrderView
ON Sales.OrderSummaryView
INSTEAD OF UPDATE
AS
BEGIN
    UPDATE Sales.Orders
    SET OrderStatus = i.OrderStatus,
        ModifiedDate = GETDATE()
    FROM Sales.Orders o
    INNER JOIN inserted i ON o.OrderID = i.OrderID;
END;

مع مشغلات DML، يمكنك الوصول إلى الجداول الزائفة المدخلةوالمحذوفة . تخزن هذه الجداول المؤقتة نسخا من الصفوف المتأثرة. INSERT تملأ العمليات الجدول المدرج ، والعمليات DELETE تملأ الجدول المحذوف ، والعمليات UPDATE تملأ كلا الجدولين بقيم قديمة في الحذف وجديدة في القيم المدرجة.

تنفيذ محفزات لأحداث محددة

تحدد أي أحداث تعديل البيانات تفعل مشغلك. يمكن لمحفز واحد أن يستجيب لعدة أحداث عن طريق دمج INSERT، UPDATE، و DELETE في تعريف المحفز.

للتحكم الدقيق، تقوم بإنشاء محفزات منفصلة لكل عملية. هذا النهج يبسط الكود الخاص بك ويجعل المحفزات أسهل في الصيانة:

CREATE TRIGGER tr_LogPriceChanges
ON Products.Catalog
AFTER UPDATE
AS
BEGIN
    IF UPDATE(Price)
    BEGIN
        INSERT INTO Audit.PriceHistory (ProductID, OldPrice, NewPrice, ChangeDate)
        SELECT d.ProductID, d.Price, i.Price, GETDATE()
        FROM deleted d
        INNER JOIN inserted i ON d.ProductID = i.ProductID
        WHERE d.Price <> i.Price;
    END;
END;

في نفس الوقت، قد تدمج الأحداث عندما ينطبق نفس المنطق على عدة عمليات. على سبيل المثال، يمكنك إنشاء محفز تدقيق واحد يستجيب ل INSERT، UPDATEو DELETE:

CREATE TRIGGER tr_AuditEmployeeChanges
ON HR.Employees
AFTER INSERT, UPDATE, DELETE
AS
BEGIN
    DECLARE @Operation NVARCHAR(10);
    
    IF EXISTS (SELECT * FROM inserted) AND NOT EXISTS (SELECT * FROM deleted)
        SET @Operation = 'INSERT';
    ELSE IF EXISTS (SELECT * FROM inserted) AND EXISTS (SELECT * FROM deleted)
        SET @Operation = 'UPDATE';
    ELSE
        SET @Operation = 'DELETE';
    
    INSERT INTO Audit.EmployeeLog (EmployeeID, Operation, ChangeDate)
    SELECT COALESCE(i.EmployeeID, d.EmployeeID), @Operation, GETDATE()
    FROM inserted i
    FULL OUTER JOIN deleted d ON i.EmployeeID = d.EmployeeID;
END;

تساعدك الدالة UPDATE() في تحديد الأعمدة التي تغيرت. تقوم بفحص أعمدة محددة لتجنب معالجة غير ضرورية عندما تكون حقول معينة فقط هي المهمة لمنطق عملك.

تطبيق أفضل ممارسات المحفزات

تؤثر المحفزات على أداء قاعدة البيانات لأنها تنفذ مع كل عملية تأهيل. تكتب كود تفعيل فعال لتقليل التأثير على معدل المعاملات.

حافظ على منطق المحفز مركزا وبسيطا. نفذ العمليات الأساسية فقط داخل جسم المحفز. للعمليات المعقدة أو التي تستغرق وقتا طويلا، فكر في تسجيل تفاصيل الأحداث ومعالجتها بشكل غير متزامن عبر مهمة منفصلة:

CREATE TRIGGER tr_QueueLargeOrders
ON Sales.Orders
AFTER INSERT
AS
BEGIN
    INSERT INTO Processing.OrderQueue (OrderID, TotalAmount, QueuedDate)
    SELECT OrderID, TotalAmount, GETDATE()
    FROM inserted
    WHERE TotalAmount > 10000;
END;

تجنب العمليات التكرارية حيث يؤدي تعديل الزناد إلى إطلاق نفس الزناد مرة أخرى. حدد RECURSIVE_TRIGGERS خيار قاعدة البيانات بشكل مناسب وصمم محفزاتك لمنع تكرار الحلقات التي لا تنتهي.

تعامل مع الأخطاء بشكل صحيح داخل المحفزات. سلوك المعاملات يعتمد على طريقة التعامل مع الأخطاء لديك. إذا واجه المحفز خطأ ولم تتعامل معه، يقوم SQL Server بالتراجع عن كل من الزناد والعبارة الأصلية:

CREATE TRIGGER tr_ValidateOrderDate
ON Sales.Orders
AFTER INSERT, UPDATE
AS
BEGIN
    IF EXISTS (SELECT * FROM inserted WHERE OrderDate > GETDATE())
    BEGIN
        THROW 50001, 'Order date cannot be in the future', 1;
    END;
END;

وثق محفزاتك بشكل كامل. يحتاج المطورون الآخرون إلى فهم سبب وجود المحفزات وما الذي تفعله، لأنها تنفذ بشكل غير مرئي أثناء العمليات العادية في قاعدة البيانات.

الآن بعد أن فهمت كيفية إنشاء وتنفيذ المحفزات، أصبحت مستعدا لاستكشاف كيفية تكاملها مع كائنات البرمجة الأخرى لبناء حلول قواعد بيانات شاملة.