SQL触发器-提交更新和CATCH过程块

时间:2018-10-17 10:07:25

标签: sql sql-server tsql sql-server-2012

我在执行存储过程的表上有一个触发器。执行的存储过程具有TRY / CATCH,因此,如果有错误,则会在日志表中插入一行。

存储过程失败时,出现以下错误:

The current transaction cannot be committed and cannot support operations that write to the log file. Roll back the transaction.

如何使更新生效并同时执行存储过程中的CATCH?如果我添加:

IF @@TRANCOUNT > 0 
ROLLBACK TRAN

到存储过程,然后出现以下错误:

The transaction ended in the trigger. The batch has been aborted.

触发:

ALTER TRIGGER [dbo].[trigger123] ON [dbo].[tbl321]
AFTER UPDATE
AS
BEGIN
SET NOCOUNT ON;
IF UPDATE (status) 
BEGIN

 IF EXISTS (--some condition)
BEGIN
EXEC SProc 
END

END
END

SProc:

ALTER PROCEDURE [dbo].[SProc ]
AS  
BEGIN  

DECLARE @ErrorMessage NVARCHAR(4000);
DECLARE @ErrorSeverity INT;
DECLARE @ErrorState INT;

BEGIN TRY

   select @sql = '
   declare @error1 varchar(255),
   @error2 varchar(255),
   @error3 varchar(255)

   Exec SomeDB.DBO.ConfirmStatus  ''A10594'',@error1 output,@error2 output,@error3 output

   if ISNULL(@error1,0) <> 0
   begin
        set @error1 = ISNULL(@error2,'''') + '' '' + ISNULL(@error3,'''') + '' '' + ISNULL(@error1,0)
        RAISERROR (@error1, 16, 1)
   end'
   from jobs j

   exec(@sql) at [linked_server]

   update status
    set status_prev = 1

END TRY

BEGIN CATCH

SELECT
@ErrorMessage = ERROR_MESSAGE(),
@ErrorSeverity = ERROR_SEVERITY(),
@ErrorState = ERROR_STATE()

INSERT INTO error_log (error_datetime, [error_message])
SELECT
    GETDATE(),
    'Msg: ' + ISNULL(CONVERT(VARCHAR, ERROR_NUMBER()), 'N/A') + ', Level: ' + ISNULL(CONVERT(VARCHAR, @ErrorSeverity), 'N/A') + ', Line: ' + ISNULL(CONVERT(VARCHAR, ERROR_LINE()), 'N/A') + ', Error: ' + ISNULL(@ErrorMessage, 'N/A')

END CATCH
END

1 个答案:

答案 0 :(得分:0)

我能够修改存储过程以不使用try / catch。这可以满足我的需求。

ALTER PROCEDURE [dbo].[SProc ]
AS  
BEGIN  

DECLARE @error table (error1 varchar(255))

DECLARE @ErrorMessage NVARCHAR(4000);
DECLARE @ErrorSeverity INT;
DECLARE @ErrorState INT;

BEGIN TRY

   select @sql = '
   declare @error1 varchar(255),
   @error2 varchar(255),
   @error3 varchar(255)

   Exec SomeDB.DBO.ConfirmStatus  ''A10594'',@error1 output,@error2 output,@error3 output

   if ISNULL(@error1,0) <> 0
   begin
        set @error1 = ISNULL(@error2,'''') + '' '' + ISNULL(@error3,'''') + '' '' + ISNULL(@error1,0)
        select @error1
   end'
   from jobs j

insert into @error
exec(@sql) at [linked_server]

if exists (select top 1 error1 from @error)
   begin

INSERT INTO error_log (error_datetime, [error_message])
SELECT
    GETDATE(),
    (select top 1 error1 from @error)

else
   update status
    set status_prev = 1

END