SQL Server Trigger After Update


By:
Overview

Continuing with the model from the previous chapter, now we are going to use a trigger that fires when an update statement is executed.

Sample Test Scenario

As you may remember from previous chapters, triggers that handle update statements differ between those that only deal with insert statements, because they make use of deleted pseudo table as well. This is because an update statement can be considered as a delete followed by an insert.

But having both the deleted and inserted tables at your disposal does not mean that you have to always use them. As you will see in the next sample, we will create a trigger that handles update events to disallow updates on items from orders that were already processed. You will find this trigger very similar to the one we made in the previous chapter to handle insert statements.

CREATE TRIGGER TR_U_PurchaseOrderDetail
ON dbo.PurchaseOrderDetail
FOR UPDATE
AS
IF EXISTS (   SELECT 0
              FROM   dbo.PurchaseOrderHeader POH
                     INNER JOIN Inserted I ON I.PurchaseOrderID = POH.PurchaseOrderID
              WHERE  POH.IsProcessed = 'Y') 
    BEGIN
        ; THROW 51000, 'Purchase Order Items can only be updated before processing order ', 1;
    END;

Now let's see the actual items on PurchaseOrderHeader and PurchaseOrderDetail tables so we can test our trigger.

Sample Tables Initial load of test tables.

Let's see what happens when we try to update an approved purchase order, like order number 1.

UPDATE dbo.PurchaseOrderDetail 
 SET OrderQty = 2 
 WHERE PurchaseOrderID = 1
 AND PurchaseOrderDetailID = 1

As you can see in the image below the update fails with an error message saying that "Purchase Order Items can only be updated before processing order".

Testing the trigger The update fails because of trigger condition.

Now let's see what happens when we update items on a purchase order that has not been approved yet, like purchase order number 3.

UPDATE dbo.PurchaseOrderDetail 
 SET OrderQty = 2 
 WHERE PurchaseOrderID = 3
 AND PurchaseOrderDetailID = 4

On the image below we can see that there were no errors and one row was affected.

Testing the trigger The update succeed because it complies with trigger condition that only allow changes in quantities on unprocessed orders.

Finally, if we query the PurchaseOrderHeader and PurchaseOrderDetail tables we can see that the quantity for item 4 in order 3 was changed.

Testing the trigger State of test tables after update.

Using the deleted table in a UPDATE trigger

Suppose that we have to check that in case an item's price is updated, the new price cannot be lower than 90 percent of the previous price. In other words, only 10 percent discounts are allowed. In order to code this we only need to add an IF block to our trigger.

ALTER TRIGGER TR_U_PurchaseOrderDetail
ON dbo.PurchaseOrderDetail
FOR UPDATE
AS
IF EXISTS (   SELECT 0
              FROM   dbo.PurchaseOrderHeader POH
                     INNER JOIN Inserted I ON I.PurchaseOrderID = POH.PurchaseOrderID
              WHERE  POH.IsProcessed = 'Y' )
    BEGIN
        THROW 51000, 'Purchase Order Items can only be updated before processing order ', 1;
    END;
 
IF EXISTS (   SELECT 0
              FROM   Inserted I
                     INNER JOIN Deleted D ON D.PurchaseOrderDetailID = I.PurchaseOrderDetailID
              WHERE  I.UnitPrice < D.UnitPrice * 0.9 )
    BEGIN
        THROW 51000, 'Only up to 10% discount price is allowed', 1;
    END;
GO

In the code you will see that we can join inserted and deleted pseudo tables to compare the change in the data with the execution of the update statement.

Let's try to update the unit price of apples (PurchaseOrderDetailID = 4) in purchase order number 3, which is $20 and try to set it to $5.

UPDATE dbo.PurchaseOrderDetail
SET    UnitPrice = 5
WHERE  PurchaseOrderID = 3
       AND PurchaseOrderDetailID = 4;

As you can see in the image below we see an error message telling us that discounts are only allowed up to 10 percent.

Testing the trigger 4 We can

Since apples have a unit price of $20, we cannot update the price to a value lower than $18. Let's try to set its price to $19.

UPDATE dbo.PurchaseOrderDetail
SET    UnitPrice = 19
WHERE  PurchaseOrderID = 3
       AND PurchaseOrderDetailID = 4;

In the image below we can see that we were able to change the price.

Testing the trigger 5 State of test tables after update.
Additional Information





Comments For This Article

















get free sql tips
agree to terms