提问人:John 提问时间:10/25/2023 最后编辑:John 更新时间:10/27/2023 访问量:111
继续执行而不引发异常
Continue execution without throw the exception
问:
我在 while 循环中运行一个过程,当出现异常时,它会退出该过程。 但是我希望该过程应该在 while 循环中继续执行其他实体,并且应该退出该过程,而是会在表中记录错误。这样我们就可以在过程完成执行后对表进行处理。 如果您有任何解决方案,请告诉我。
CREATE PROC [DYNAMIC_PROC_MAIN] AS
BEGIN
SET NOCOUNT ON
/* Variable Declaration */
DECLARE @CheckError INT = 0;
DECLARE @ErrorMessage VARCHAR(4000);
DECLARE @Current_date datetime
DECLARE @VMaxlevel bigint
DECLARE @RowCount bigint
DECLARE @Vraa_name VARCHAR(50)
DECLARE @Vformula VARCHAR(50)
DECLARE @Vlevel INT
--DECLARE @Vmonth VARCHAR(50) = '202306'
DECLARE @InputValue varchar(1000)
DECLARE @LastRefreshDate datetime
DECLARE @number_of_rows int
DECLARE @row_count INT
DECLARE @Counter INT
SET @Counter = 1
DECLARE @CounterList INT
SET @CounterList = 1
DECLARE @Vtemp VARCHAR(4000)
SET @VMaxlevel =
(select max(level_id)
FROM Level_t)
WHILE (@Counter <= @VMaxlevel )
BEGIN TRY
--Print(@VMaxlevel)
Set @InputValue = @MonthValue
SELECT @Current_date=GETUTCDATE()
SELECT @LastRefreshDate=GETUTCDATE()
--Print(@Counter)
SET @RowCount =
(SELECT count(distinct lt.ID) FROM Level_t2 lt
WHERE lt.level=@counter)
WHILE (@CounterList <= @RowCount )
BEGIN
/* Begin creation a temp table to store recrods in runtime */
BEGIN
IF OBJECT_ID('tempdb..#kpi_maintmptbl') IS NOT NULL
BEGIN
--print 'Hello'
DROP TABLE #kpi_maintmptbl
END
--GO
create table #kpi_maintmptbl
with (
DISTRIBUTION = ROUND_ROBIN
,HEAP
)
AS (select distinct lt.name FROM Level_t3 lt
where lt.level=@CounterList)
END
/* End creation a temp table to store recrods in runtime */
DECLARE @recordCount int = (SELECT COUNT(1) from #kpi_maintmptbl)
DECLARE @counter1 int = 1
DECLARE @name VARCHAR(50) -- database name
WHILE @counter1 <= @recordCount
BEGIN
SET @name = (SELECT [name]
FROM(SELECT *, ROW_NUMBER() OVER(ORDER BY [raa_name]) AS RN
FROM #kpi_maintmptbl) as T
WHERE RN = @counter1)
PRINT @name
PRINT @Vlevel
Print @counter1
EXEC DYNAMIC_PROC @name
SET @counter1 = @counter1 + 1
END
SET @CounterList = @CounterList +1
END
--SET @Counter = @Counter +1
END TRY
Begin Catch
DECLARE
@ErrorSeverity INT,
@ErrorState INT;
SELECT @ErrorMessage = ERROR_MESSAGE(),
@ErrorSeverity = ERROR_SEVERITY(),
@ErrorState = ERROR_STATE();
RAISERROR(@ErrorMessage, @ErrorSeverity, @ErrorState);
SELECT @Current_date=GETUTCDATE()
SET @CheckError = ERROR_NUMBER()
SET @ErrorMessage = concat(@name,'-',ERROR_MESSAGE())
SELECT @Current_date=GETUTCDATE()
INSERT INTO dl_config.CL_Error_Log
VALUES('DYNAMIC_PROC_MAIN',@CheckError,@ErrorMessage,@Current_date,NULL);
--THROW
End Catch
SET @Counter = @Counter +1
End
GO
答:
0赞
Zohar Peled
10/25/2023
#1
如果您希望您的过程在出错时继续,则不应在捕获它(或使用 )后抛出它(或使用 )。相反,您可以使用表、表变量或临时表来存储错误信息并继续循环。raiseerror
下面是一个示例:
DECLARE @Errors as Table
(
Severity int,
State int,
Message nvarchar(4000)
);
WHILE (@Counter <= @VMaxlevel )
BEGIN TRY
EXEC DYNAMIC_PROC
END TRY
BEGIN CATCH
INSERT INTO @Errors(Severity, State, Message)
VALUES(ERROR_SEVERITY(), ERROR_STATE(), ERROR_MESSAGE());
END CATCH
-- This will ensure the counter will be raised even in case of an error
SET @Counter = @Counter +1
END
顺便说一句,循环通常是在 SQL 中使用的错误工具,所以如果可以完全避免循环,那可能是一个更好的做法。
评论
0赞
John
10/25/2023
@GarethD 感谢您的回复。我会尝试确认。
0赞
John
10/25/2023
@GarethD Loops 实际上用于自动化。除此之外还有更好的方法吗?你能提出建议吗?
1赞
Zohar Peled
10/25/2023
我不是 GarethD,但在不知道具体细节的情况下,很难判断你是否真的可以避免循环。
0赞
GarethD
10/27/2023
#2
您的问题是您现在已经将递增计数器移到了循环本身之外。你有这个:SET
WHILE(@Counter <= @VMaxlevel)
BEGIN TRY
....
END TRY
BEGIN CATCH
....
END CATCH
SET @Counter = @Counter + 1;
由于您没有使用 is using your to determine 语句。这里需要一个额外的计数器,所以你在try/catch块之外,但在循环内部增加计数器BEGIN/END
WHILE
BEGIN TRY/END CATCH
BEGIN/END
WHILE(@Counter <= @VMaxlevel)
BEGIN
BEGIN TRY
....
END TRY
BEGIN CATCH
....
END CATCH
SET @Counter = @Counter + 1;
END
老实说,我几乎无法理解您的代码试图做什么,但我无法想象任何一种情况,即循环中的循环是一个好主意。在不知道修复程序是什么的情况下,很难确切地说出修复程序是什么,但几乎可以肯定的是,有一种更有效、更易于维护的方法。DYNAMIC_PROC
如果你的嵌套 BEGIN/END 和循环变得如此复杂,以至于即使是作者也无法跟踪哪个块中的内容,那么可能是时候重新考虑这种方法了......
评论
CATCH