Showing posts with label ROLLBACK. Show all posts
Showing posts with label ROLLBACK. Show all posts

Wednesday, 12 March 2014

ROLLBACK statement in TRIGGER

Introduction

One of the junior developers asks me a question that there is a table and an associate trigger with this table, If a certain condition fails in the trigger that it rollback the entire transaction.   

To understand it let’s take an example

We have a table called [dbo].[tbl_EMPMSTR]
The table contains a trigger named [dbo].[trg_CHECKSAL]
The trigger works like a CHECK constraint. If the salary is <= 500 then it should ROLLBACK TRANSACTION.

Step-1 [ Create the Base Table ]

IF OBJECT_ID(N'dbo.tbl_EMPMSTR', N'U') IS NOT NULL
   BEGIN
      DROP TABLE [dbo].[tbl_EMPMSTR];
   END
GO
CREATE TABLE [dbo].[tbl_EMPMSTR]
 (
   EMPID    INT         NOT NULL IDENTITY PRIMARY KEY,
   EMPNAME  VARCHAR(50) NOT NULL,
   EMPSAL   INT         NOT NULL
 );
GO

Step-2 [ Create Trigger ]

IF OBJECT_ID(N'dbo.trg_CHECKSAL', N'TR')IS NOT NULL
   BEGIN
      DROP TRIGGER [dbo].[trg_CHECKSAL];
   END        
GO

CREATE TRIGGER [dbo].[trg_CHECKSAL]
ON [dbo].[tbl_EMPMSTR]
AFTER INSERT  
AS
BEGIN
   DECLARE @v_SAL INT = 0;
   IF EXISTS(SELECT * FROM inserted)
      BEGIN
       SET @v_SAL = (SELECT EMPSAL FROM inserted);
       IF @v_SAL<= 500
          BEGIN  
             RAISERROR (N'SALARY not Less then the Rs. 500.00', 16, 1);
             ROLLBACK TRANSACTION;
          END
      END
END
GO

Step-3 [ Now Try some Insert Statement ]

INSERT INTO [dbo].[tbl_EMPMSTR]
       (EMPNAME, EMPSAL)
VALUES('Chandan Bannerjee', 700);
GO

(1 row(s) affected)

INSERT INTO [dbo].[tbl_EMPMSTR]
       (EMPNAME, EMPSAL)
VALUES('Joydeep Das', 300);         

Msg 50000, Level 16, State 1, Procedure trg_CHECKSAL, Line 12
SALARY not Less then the Rs. 500.00
Msg 3609, Level 16, State 1, Line 1
The transaction ended in the trigger. The batch has been aborted.

Step-4 [ Observation ]

SELECT * FROM [dbo].[tbl_EMPMSTR];
EMPID       EMPNAME                     EMPSAL
----------- --------------------------- -----------
1           Chandan Bannerjee           700

(1 row(s) affected)

Here the second insert statement which have the employee name JOYDEEP DAS has ROLLBACKED as the salary is less than 500.


Hope you like it.



Posted by: MR. JOYDEEP DAS

Friday, 29 June 2012

COMMIT and ROLLBACK TRANSACTION in Triggers


One of my friends asks me to write an article related to COMMIT and ROLLBACK TRANSACTION in Triggers.
After reading one of my previous article
DELETE restriction of VIEWS
Where I am using a ROLLBACK TRAN in a trigger (INSTEAD OF DELETE trigger), he had a question on mid that without using the BEGIN TRANSACTION on the Trigger, can we us the ROLLBACK TRANSACTION. It is better, if you read my previous article to understand the complete scenario.

The executions of COMMIT TRANSACTION and ROLLBACK TRANSACTION inside the trigger are possible.
When a trigger executes, an implicit transaction is started. If the trigger completes execution and @@TRANCOUNT = 0, error 3609 occurs and the batch is terminated.
If a BEGIN TRANSACTION statement is issued in a trigger, it creates a nested transaction. In this situation, when a COMMIT TRANSACTION statement is executed, the statement will apply only to the nested transaction.
However, in the case of TRIGGER, if BEGIN TRANSACTION is executed before or after the COMMIT TRANSACTION, the error does not occur.
In another scenario of TRIGGER, if BEGIN TRANSACTION is executed after the ROLLBACK TRANSACTION, the error does not occur.
Now I am given an example to illustrate my points. Here I am taking my previous article example to demonstrate it.

IF OBJECT_ID('emp_data') IS NOT NULL
   BEGIN
     DROP TABLE emp_data
   END
GO

CREATE TABLE emp_data
       (
         IDNO     INT         NOT NULL IDENTITY(1,1) PRIMARY KEY,
         EMPNAME  VARCHAR(50) NOT NULL,
         EMPGRADE VARCHAR(1)  NOT NULL,
         CONSTRAINT CHK_emp_data_EMPGRADE
         CHECK (EMPGRADE IN('A','B','C'))
        )
      
GO  
-- Insert records

INSERT INTO emp_data
       (EMPNAME, EMPGRADE)
VALUES ('Sudip Das', 'A'),
       ('Joydeep Das', 'B'),
       ('Sangram Jit', 'B'),
       ('Tuhin Shinah', 'B'),
       ('Bhola', 'C')   
     
-- Display records

SELECT IDNO, EMPNAME, EMPGRADE
FROM   emp_data      
    
-- Output

IDNO  EMPNAME           EMPGRADE
1     Sudip Das         A
2     Joydeep Das       B
3     Sangram Jit       B
4     Tuhin Shinah      B
5     Bhola             C
   
-- Creation of VIEWS

IF OBJECT_ID('view_emp_data') IS NOT NULL
   BEGIN
     DROP VIEW  view_emp_data
   END
GO

CREATE VIEW  view_emp_data
AS
SELECT IDNO, EMPNAME, EMPGRADE
FROM   emp_data

GO

-- Display the Records of Views

SELECT IDNO, EMPNAME, EMPGRADE
FROM   view_emp_data

-- Output from View

IDNO  EMPNAME           EMPGRADE
1     Sudip Das         A
2     Joydeep Das       B
3     Sangram Jit       B
4     Tuhin Shinah      B
5     Bhola             C

Now I am creating the trigger with simple ROLLBACK TRANSACTION without any BEGIN TRANSACTION.        


IF OBJECT_ID('trg_RestrictDEL') IS NOT NULL
   BEGIN
     DROP TRIGGER trg_RestrictDEL
   END
GO
      
CREATE TRIGGER trg_RestrictDEL ON view_emp_data
INSTEAD OF DELETE
AS
  BEGIN

       IF @@rowcount > 0
       BEGIN
          RAISERROR('Rows from Views Named: view_emp_data, CANNOT be DELETED!', 16, 2 )
          ROLLBACK TRANSACTION
       END
      
END
GO

Now I am trying to DELETE records
DELETE view_emp_data
WHERE IDNO=3
Please Look at the Error Message. The Error portion is highlighted here.
Msg 50000, Level 16, State 2, Procedure trg_RestrictDEL, Line 10
Rows from Views Named: view_emp_data, CANNOT be DELETED!
Msg 3609, Level 16, State 1, Line 1
The transaction ended in the trigger. The batch has been aborted.
Now I am trying to ALTER this Trigger with BIGIN TRANSACTION, immediate after the ROLLBACK TRANSACTION. We find no Error after execution. (Please try this)
IF OBJECT_ID('trg_RestrictDEL') IS NOT NULL
   BEGIN
     DROP TRIGGER trg_RestrictDEL
   END
GO
      
CREATE TRIGGER trg_RestrictDEL ON view_emp_data
INSTEAD OF DELETE
AS
  BEGIN

       IF @@rowcount > 0
       BEGIN
                 BEGIN TRAN
                 RAISERROR('Rows from Views Named: view_emp_data, CANNOT be DELETED!', 16, 2 )
                 ROLLBACK TRANSACTION
                 BEGIN TRANSACTION
       END
      
END
GO
Now execute the DELETE statement again.
DELETE view_emp_data
WHERE IDNO=3
Msg 50000, Level 16, State 2, Procedure trg_RestrictDEL, Line 10
Rows from Views Named: view_emp_data, CANNOT be DELETED!

No error message.

Hope you like it.

Posted by: MR. JOYDEEP DAS