не попасть в блок Catch - PullRequest
       18

не попасть в блок Catch

0 голосов
/ 10 февраля 2019

У меня есть хранимая процедура SQL с Transaction.Я фактически написал SP с тремя этапами, каждый делает что-то в другой таблице.Проблема в том, что когда SP достигает 3-го этапа, один из столбцов равен varchar(20), но я вставил строку с 30 символами и, хотя SP завершился успешно, в то время как я исключил ее, чтобы попасть в блок Catch и сделатьROLLBACK.3-й этап не был зафиксирован, и в таблицу не было добавлено ни одной строки, но все равно кажется, что Transcation не работает и два первых этапа зафиксированы.

Вот мой 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

1 Ответ

0 голосов
/ 10 февраля 2019

Вы можете ясно видеть, что если вы передадите строку, длина которой больше допустимой, вы получите следующую ошибку, и будет выполнена откат транзакции:

Сообщение 8152, уровень 16, Состояние 30, строка 18 Строковые или двоичные данные будут усечены.

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];

Итак, в вашем коде нет ничего плохого.Но вы передаете строки через переменные, и значение автоматически усекается, чтобы соответствовать длине переменной.

Итак, проверьте следующее:

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];

Итак, вы можете проверить, еслиВходные параметры действительны до вызова хранимой процедуры или для увеличения значения входных параметров и зависят от двигателя.В любом случае, я предпочитаю проверять данные перед их использованием - мне это кажется более понятным (почему мы позволяем пользователю вводить имя с большей длиной, если это не разрешено?).

...