Rob*_*gie 4 sql-server stored-procedures error-handling sql-server-2014
作为 Microsoft SQL Server 2014 上的一三个一般问题,也许我应该已经知道答案,或者甚至可能曾经知道 -
当我的存储过程运行其他存储过程时,如何找出哪个存储过程的代码产生了错误?
是否有一种特殊的方法来处理来自 Transact-SQL 的错误,以标识给定存储过程中的错误位置?
存储过程中的程序代码能否获得它所在过程的名称?
如果这是唯一的方法,我准备将“SET @MyNameIs = N'HastilyWrittenProcedure”放入程序代码中。然后我可以输入“PRINT @MyNameIs + 'break.'。" 在所有的错误处理程序中。
当我的存储过程运行其他存储过程时,如何找出哪个存储过程的代码产生了错误?
在您的 CATCH 块中,您可以使用ERROR_PROCEDURE()来获取发生错误的过程或触发器的名称。
如果您只是在内部过程的 CATCH 块中使用 THROW,那么您的外部过程可以访问这些系统函数(ERROR_PROCEDURE()、ERROR_LINE() 等)以检索有关外部过程的 CATCH 块中的内部过程失败的信息。
是否有一种特殊的方法来处理来自 Transact-SQL 的错误,以标识给定存储过程中的错误位置?
在您的 CATCH 块中,您可以使用ERROR_LINE()来获取发生错误的过程或触发器的名称。
存储过程中的程序代码能否获得它所在过程的名称?
使用此代码:SELECT OBJECT_NAME(@@PROCID)获取过程本身内的过程名称。
下面是在嵌套过程场景中使用的这些示例。
使用扩展事件的另一个想法。
创建扩展事件会话以捕获错误
CREATE EVENT SESSION [Track_Errors] ON SERVER
ADD EVENT sqlserver.error_reported(
ACTION(sqlserver.client_app_name,sqlserver.client_hostname,sqlserver.database_name,sqlserver.is_system,sqlserver.server_instance_name,sqlserver.server_principal_name,sqlserver.sql_text))
ADD TARGET package0.event_file(SET filename=N'D:\some_path\track_errors',max_file_size=(50),max_rollover_files=(5))
WITH (MAX_MEMORY=4096 KB,EVENT_RETENTION_MODE=ALLOW_SINGLE_EVENT_LOSS,MAX_DISPATCH_LATENCY=30 SECONDS,MAX_EVENT_SIZE=0 KB,MEMORY_PARTITION_MODE=NONE,TRACK_CAUSALITY=ON,STARTUP_STATE=ON)
GO
ALTER EVENT SESSION [Track_Errors] ON SERVER STATE = START
Run Code Online (Sandbox Code Playgroud)
然后在你的嵌套的存储过程,使用RAISEERROR或THROW打印出扩展事件的消息列存储过程的名称。
RAISERROR ('sp_test_nested_error', 16, 1) WITH NOWAIT
THROW 50000, N'sp_test_nested_error', 1;
Run Code Online (Sandbox Code Playgroud)
下面是我用来测试的两个存储过程
-- nested stored procedure
CREATE procedure [dbo].[sp_test_nested_error]
AS
BEGIN TRY
-- Generate a divide-by-zero error
SELECT
1 / 0 AS Error;
END TRY
BEGIN CATCH
THROW 50000, N'sp_test_nested_error', 1;
END CATCH;
GO
-- parent stored procedure
CREATE procedure [dbo].[sp_test_proc]
AS
exec sp_test_nested_error
GO
Run Code Online (Sandbox Code Playgroud)
以及由此产生的扩展事件输出