JumpIntoTheWater
JumpIntoTheWater

Reputation: 1336

not getting into Catch block

I have a SQL Stored Procedure with Transaction. I actaully wrote the SP with three stages,each does something in different table. The problem is , when the SP gets to the 3rd stage, one of the columns is varchar(20) , but I inserted a string with 30 chars and eventhough the SP completed succefully , while I expceted it to get into the Catch block and make a ROLLBACK. The 3rd stage didn't commit , and no rows were added to the table, but still, it feels like the Transcation didn't work and the two first stages committed.

Here's my SQL SP:

USE [dbfoo]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO


ALTER PROCEDURE [dbo].[io_sp_admin]
@id BIGINT = 0, @firstName VARCHAR(20),@lastName VARCHAR(20) ,@email VARCHAR(50), @birthDate DATETIME
        
AS
BEGIN
       -- SET NOCOUNT ON added to prevent extra result sets from
       -- interfering with SELECT statements.
SET NOCOUNT ON;
BEGIN TRY
BEGIN TRANSACTION [TranAddEmp]
OPEN SYMMETRIC KEY io_key DECRYPTION BY CERTIFICATE foo

--stage1
DECLARE @identity BIGINT = 0 

INSERT INTO [dbo].[t1]
           ([id],
            [deleted],
            [user_name],
     VALUES
           (EncryptByKey(KEY_GUID('io_key'), CONVERT(VARBINARY(100),CAST(@id AS VARCHAR(10)))),
           0,
           'IoAdmin'

SELECT @identity = @@identity 

--satge2
INSERT INTO [dbo].[t2]
           ([id]
           ,[deleted]
           ,[user_name]
     VALUES
           (@identity,
           EncryptByKey(KEY_GUID('io_key'), CONVERT(VARBINARY(100),CAST(@ms_zehut AS VARCHAR(10)))),
           0,
           'IoAdmin'

--stage 3
INSERT INTO t3(
id,
lastName,
firstName,
birtdate,
email)

SELECT
 @identity,
 @lastName , 
 @firstName , 
@birthDate,
 @email 

CLOSE ALL SYMMETRIC KEYS
           
SELECT CAST(1 as BIT) as 'Status', 'Succeeded' as 'ReturnMessage'   
COMMIT TRANSACTION [TranAddEmp]     
END TRY

BEGIN CATCH
 
SELECT CAST(0 as BIT) as 'Status', 'ADMIN - Add employee failed' as 'ReturnMessage'       
ROLLBACK TRANSACTION [TranAddEmp]     
END CATCH
END

Upvotes: 4

Views: 57

Answers (1)

gotqn
gotqn

Reputation: 43636

You can see clearly that If you pass a string, which has bigger length then allowed, you will get the following error and the transaction is a rollback is performed:

Msg 8152, Level 16, State 30, Line 18 String or binary data would be truncated.

DROP TABLE IF EXISTS [dbo].[DataSource];

CREATE TABLE [dbo].[DataSource]
(
    [value] VARCHAR(8)
);

BEGIN TRY

    BEGIN TRANSACTION

    INSERT INTO [dbo].[DataSource] ([value])
    VALUES ('123');

    INSERT INTO [dbo].[DataSource] ([value])
    VALUES ('very large string');

    COMMIT TRANSACTION

END TRY
BEGIN CATCH

    IF @@TRANCOUNT > 0
    BEGIN;
        ROLLBACK TRANSACTION;
    END;

    THROW;

END CATCH

SELECT *
FROM [dbo].[DataSource];

So, there is nothing wrong with your code. But you are passing the strings through variables and the the value is automatically truncated to fit the variable length.

So, check the following:

DROP TABLE IF EXISTS [dbo].[DataSource];

CREATE TABLE [dbo].[DataSource]
(
    [value] VARCHAR(8)
);

DECLARE @values VARCHAR(8) = 'very large string';

SELECT @values;

BEGIN TRY

    BEGIN TRANSACTION

    INSERT INTO [dbo].[DataSource] ([value])
    VALUES ('123');

    INSERT INTO [dbo].[DataSource] ([value])
    VALUES (@values);

    COMMIT TRANSACTION

END TRY
BEGIN CATCH

    IF @@TRANCOUNT > 0
    BEGIN;
        ROLLBACK TRANSACTION;
    END;

    THROW;

END CATCH

SELECT *
FROM [dbo].[DataSource];

So, you can check the if the input parameters are valid before calling the stored procedure or to increase the value of the input parameters and rely on the engine. Anyway, I prefer validating the data before using it - it's seems more clear for me (why we are allowing a user to enter name with larger length if it is not allowed?).

Upvotes: 2

Related Questions