Dom*_*nic 39 sql t-sql sql-server try-catch
CREATE PROCEDURE [dbo].[PL_GEN_PROVN_NO1]
@GAD_COMP_CODE VARCHAR(2) =NULL,
@@voucher_no numeric =null output
AS
BEGIN
DECLARE @NUM NUMERIC
DECLARE @PNO NUMERIC
SET @PNO = 0
DECLARE @PNO1 NUMERIC
SET @PNO1=0
-- begin transaction
IF NOT EXISTS (select GLDC_NEXT_PRV_NO
FROM GLAS_FINANCIAL_DOCUMENTS
WHERE GLDC_COMP_CODE = @GAD_COMP_CODE
AND GLDC_DOC_CODE = 'JV' )
BEGIN
RAISERROR ('Error in generating provision number..',16,1)
-- ROLLBACK TRANSACTION
END
ELSE
SELECT @PNO=ISNULL(GLDC_NEXT_PRV_NO,0)+1
FROM GLAS_FINANCIAL_DOCUMENTS
WHERE GLDC_COMP_CODE = @GAD_COMP_CODE
AND GLDC_DOC_CODE = 'JV'
UPDATE GLAS_FINANCIAL_DOCUMENTS
SET GLDC_NEXT_PRV_NO = @PNO
WHERE GLDC_COMP_CODE = @GAD_COMP_CODE
AND GLDC_DOC_CODE = 'JV'
set @@VOUCHER_NO=@PNO
--commit transaction
END
Run Code Online (Sandbox Code Playgroud)
在这个过程中如何处理try catch异常?
Pre*_*gha 43
看到这里
CREATE PROCEDURE [dbo].[PL_GEN_PROVN_NO1]
@GAD_COMP_CODE VARCHAR(2) =NULL,
@@voucher_no numeric =null output
AS
BEGIN
begin try
-- your proc code
end try
begin catch
-- what you want to do in catch
end catch
END -- proc end
Run Code Online (Sandbox Code Playgroud)
Rem*_*anu 31
由于事务的复杂性增加,Transact-SQL比C#或C++尝试/捕获块更棘手.CATCH块必须检查xact_state()函数并确定它是否可以提交或必须回滚.我在博客中介绍了这个主题,并且有一篇文章介绍了如何使用try catch块正确处理事务,包括可能的嵌套事务:异常处理和嵌套事务.
create procedure [usp_my_procedure_name]
as
begin
set nocount on;
declare @trancount int;
set @trancount = @@trancount;
begin try
if @trancount = 0
begin transaction
else
save transaction usp_my_procedure_name;
-- Do the actual work here
lbexit:
if @trancount = 0
commit;
end try
begin catch
declare @error int, @message varchar(4000), @xstate int;
select @error = ERROR_NUMBER(),
@message = ERROR_MESSAGE(), @xstate = XACT_STATE();
if @xstate = -1
rollback;
if @xstate = 1 and @trancount = 0
rollback
if @xstate = 1 and @trancount > 0
rollback transaction usp_my_procedure_name;
raiserror ('usp_my_procedure_name: %d: %s', 16, 1, @error, @message) ;
return;
end catch
end
Run Code Online (Sandbox Code Playgroud)
ash*_*awg 12
TRY/CATCH错误处理可以在过程内部或外部(或两者)进行.以下示例演示了两种情况下的错误处理.
如果要进一步试验,可以在Stack Exchange Data Explorer上分叉查询.
(这使用临时存储过程 ......我们无法在SEDE上创建常规 SP,但功能相同.)
--our Stored Procedure
create procedure #myProc as --we can only create #temporary stored procedures on SEDE.
begin
BEGIN TRY
print 'This is our Stored Procedure.'
print 1/0 --<-- generate a "Divide By Zero" error.
print 'We are not going to make it to this line.'
END TRY
BEGIN CATCH
print 'This is the CATCH block within our Stored Procedure:'
+ ' Error Line #'+convert(varchar,ERROR_LINE())
+ ' of procedure '+isnull(ERROR_PROCEDURE(),'(Main)')
--print 1/0 --<-- generate another "Divide By Zero" error.
-- uncomment the line above to cause error within the CATCH ¹
END CATCH
end
go
--our MAIN code block:
BEGIN TRY
print 'This is our MAIN Procedure.'
execute #myProc --execute the Stored Procedure
--print 1/0 --<-- generate another "Divide By Zero" error.
-- uncomment the line above to cause error within the MAIN Procedure ²
print 'Now our MAIN sql code block continues.'
END TRY
BEGIN CATCH
print 'This is the CATCH block for our MAIN sql code block:'
+ ' Error Line #'+convert(varchar,ERROR_LINE())
+ ' of procedure '+isnull(ERROR_PROCEDURE(),'(Main)')
END CATCH
Run Code Online (Sandbox Code Playgroud)
以下是按原样运行上述sql的结果:
This is our MAIN Procedure.
This is our Stored Procedure.
This is the CATCH block within our Stored Procedure: Error Line #5 of procedure #myProc
Now our MAIN sql code block continues.
Run Code Online (Sandbox Code Playgroud)
¹从存储过程的CATCH块中取消注释"附加错误行" 将产生:
This is our MAIN procedure.
This is our Stored Procedure.
This is the CATCH block within our Stored Procedure: Error Line #5 of procedure #myProc
This is the CATCH block for our MAIN sql code block: Error Line #13 of procedure #myProc
Run Code Online (Sandbox Code Playgroud)
²从MAIN过程中取消注释"附加错误行" 将产生:
This is our MAIN Procedure.
This is our Stored Pprocedure.
This is the CATCH block within our Stored Procedure: Error Line #5 of procedure #myProc
This is the CATCH block for our MAIN sql code block: Error Line #4 of procedure (Main)
Run Code Online (Sandbox Code Playgroud)
关于存储过程和错误处理的主题,使用单个动态存储过程处理多个其他过程或代码段的错误可能会有所帮助(并且更整洁).
这是一个例子:
--our error handling procedure
create procedure #myErrorHandling as
begin
print ' Error #'+convert(varchar,ERROR_NUMBER())+': '+ERROR_MESSAGE()
print ' occurred on line #'+convert(varchar,ERROR_LINE())
+' of procedure '+isnull(ERROR_PROCEDURE(),'(Main)')
if ERROR_PROCEDURE() is null --check if error was in MAIN Procedure
print '*Execution cannot continue after an error in the MAIN Procedure.'
end
go
create procedure #myProc as --our test Stored Procedure
begin
BEGIN TRY
print 'This is our Stored Procedure.'
print 1/0 --generate a "Divide By Zero" error.
print 'We will not make it to this line.'
END TRY
BEGIN CATCH
execute #myErrorHandling
END CATCH
end
go
BEGIN TRY --our MAIN Procedure
print 'This is our MAIN Procedure.'
execute #myProc --execute the Stored Procedure
print '*The error halted the procedure, but our MAIN code can continue.'
print 1/0 --generate another "Divide By Zero" error.
print 'We will not make it to this line.'
END TRY
BEGIN CATCH
execute #myErrorHandling
END CATCH
Run Code Online (Sandbox Code Playgroud)
This is our MAIN procedure.
This is our stored procedure.
Error #8134: Divide by zero error encountered.
occurred on line #5 of procedure #myProc
*The error halted the procedure, but our MAIN code can continue.
Error #8134: Divide by zero error encountered.
occurred on line #5 of procedure (Main)
*Execution cannot continue after an error in the MAIN procedure.
Run Code Online (Sandbox Code Playgroud)
在TRY/CATCH block 的范围内,可以使用以下系统函数来获取有关导致CATCH块执行的错误的信息:
ERROR_NUMBER() 返回错误的编号. ERROR_SEVERITY() 返回严重性. ERROR_STATE() 返回错误状态编号. ERROR_PROCEDURE() 返回发生错误的存储过程或触发器的名称. ERROR_LINE() 返回导致错误的例程内的行号. ERROR_MESSAGE()返回错误消息的完整文本.该文本包括为任何可替换参数提供的值,例如长度,对象名称或时间. (来源)
请注意,有两种类型的SQL错误:终端和可捕获. TRY/ CATCH[显然]只能抓住"可捕获"错误.这是了解SQL错误的多种方法之一,但它可能是最有用的.
正如荷马所说,与以后相比,它"现在更好地失败"(在开发期间) ...
| 归档时间: |
|
| 查看次数: |
124622 次 |
| 最近记录: |