如何从错误消息中获取实际的存储过程行号?
Posted
技术标签:
【中文标题】如何从错误消息中获取实际的存储过程行号?【英文标题】:How can I get the actual stored procedure line number from an error message? 【发布时间】:2010-12-30 19:30:44 【问题描述】:当我使用 SQL Server 并且出现错误时,错误消息给出的行号与存储过程中的行号无关。我认为差异是由于空白和 cmets 造成的,但真的是这样吗?
如何将这两组行号相互关联?如果有人能至少给我一个正确方向的指针,我将不胜感激。
我使用的是 SQL Server 2005。
【问题讨论】:
我认为行号与 proc 的主体有关。即忽略标题。 也许***.com/questions/4550342/… 会有所帮助。 标题在哪里结束?在改变过程之后的开始之后...... AS? 它似乎从我的测试中的create proc
行开始计数。我假设您看到的是不同的东西。
在我的回答中描述:***.com/questions/2947173/…
【参考方案1】:
IIRC,它从创建该过程的批处理开始计算行数。这意味着要么是脚本的开始,要么是 create/alter proc 语句之前的最后一个“GO”语句。
查看这一点的更简单方法是提取 SQL Server 在创建对象时使用的实际文本。将输出切换到文本模式(使用默认键映射的 CTRL-T)并运行
sp_helptext proc_name
将结果复制粘贴到脚本窗口中以获得语法高亮等,并使用 goto line 功能(我认为是 CTRL-G)转到报告的错误行。
【讨论】:
当我在网格输出模式下执行此操作时,它也将行号卡住了 @codeulike - 好点,如果您使用网格输出,行号将匹配行号,因此您不需要使用 CTRL+G。我对 Grid 输出的唯一问题是它会将 TAB 字符更改为单个空格,因此您会丢失所有格式。【参考方案2】:出于习惯,我在存储过程中将LINENO 0
直接放在BEGIN
之后。在这种情况下,这会将行号 - 重置为零。然后只需将错误消息报告的行号添加到您编写LINENO 0
和宾果游戏的 SSMS 中的行号 - 您将在查询窗口中获得错误的行号。
【讨论】:
为什么不直接将“LineNo X”放在 X= 语句所在的行号处,以便自动添加到报告的行号中? @LarryBud 可能是由于存储过程中的 cmets?【参考方案3】:如果您使用 Catch 块并在 Try 块中使用 RAISERROR() 进行任何代码验证,则错误行会报告 Catch 块所在的位置,而不是真正发生错误的位置。我用它来清除它。
BEGIN CATCH
DECLARE @ErrorMessage NVARCHAR(4000);
DECLARE @ErrorSeverity INT;
DECLARE @ErrorState INT;
SELECT
@ErrorMessage = ERROR_MESSAGE() + ' occurred at Line_Number: ' + CAST(ERROR_LINE() AS VARCHAR(50)),
@ErrorSeverity = ERROR_SEVERITY(),
@ErrorState = ERROR_STATE();
RAISERROR (@ErrorMessage, -- Message text.
@ErrorSeverity, -- Severity.
@ErrorState -- State.
);
END CATCH
【讨论】:
太棒了!这是一个包含LINENO
指令的示例: ``` BEGIN TRY -- 将批处理行# 转换为文件#LINENO 21; -- 保持匹配文件 # -- 生成被零除错误。选择 1 / 0; END TRY BEGIN CATCH DECLARE @err_msg NVARCHAR(4000), @err_severity INT, @err_state INT; SET @err_msg = '在第 # 行' + cast(error_line() AS VARCHAR(50)) + ': ' + error_message(); SET @err_severity = error_severity(); SET @err_state = error_state(); RAISERROR (@err_msg, @err_severity, @err_state);结束捕获;去```【参考方案4】:
其实这个Error_number()
效果很好。
这个函数从最后一个 GO(批处理分隔符)语句开始计数,所以如果你没有使用任何 Go 空格并且它仍然显示错误的行号 - 然后将 7 添加到它,如第 7 行中的存储过程自动使用批处理分隔符。所以如果你使用 选择 Cast(Error_Number()+7 as Int) as [Error_Number] - 你会得到想要的答案。
【讨论】:
if you have not used any Go spaces and it is still showing a wrong line number - then add 7 to it, as in stored procedure in line number 7 the batch separator is used automatically.
- 这是什么意思?【参考方案5】:
在 TSQL / 存储过程中
您可能会收到如下错误:
消息 206,级别 16,状态 2,过程 myproc,第 177 行 [批处理开始第 7 行]
这意味着错误在批处理中的第 177 行。 SQL 中不是 177。你应该看到你的批处理开始的行号,在我的例子中 [7],然后你将该值添加到行号以查找错误的语句
【讨论】:
【参考方案6】:你可以用这个
CAST(ERROR_LINE() AS VARCHAR(50))
如果你想制作错误日志表,你可以使用这个:
INSERT INTO dbo.tbname( Source, Message) VALUES ( ERROR_PROCEDURE(), '[ ERROR_SEVERITY : ' + CAST(ERROR_SEVERITY() AS VARCHAR(50)) + ' ] ' + '[ ERROR_STATE : ' + CAST(ERROR_STATE() AS VARCHAR(50)) + ' ] ' + '[ ERROR_PROCEDURE : ' + CAST(ERROR_PROCEDURE() AS VARCHAR(50)) + ' ] ' + '[ ERROR_NUMBER : ' + CAST(ERROR_NUMBER() AS VARCHAR(50)) + ' ] ' + '[ ERROR_LINE : ' + CAST(ERROR_LINE() AS VARCHAR(50)) + ' ] ' + ERROR_MESSAGE())
【讨论】:
请注意,ERROR_LINE() 仅在存储过程中的 TRY/CATCH 的 CATCH 部分中可用。如果您没有发现错误,它报告的行号与 SQL Server 返回的行号相同。因此,虽然这可能有用,但无助于解决这个问题。【参考方案7】:长答案:行号从CREATE PROCEDURE
语句中计算,加上您实际运行CREATE
语句时可能在其上方的任何空白行或注释行,但不计算@ 之前的任何行987654323@声明…
我发现制作一个存储过程来进行确认要容易得多:
GO
-- =============================================
-- Author: <Author,,Name>
-- Create date: <Create Date,,>
-- Description: <Description,,>
-- =============================================
CREATE PROCEDURE ErrorTesting
-- Add the parameters for the stored procedure here
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
-- Insert statements for procedure here
SELECT 1/0
END
GO
创建完成后,可以将其切换为ALTER PROCEDURE
,并在 cmets 上方和第一个 GO
语句的上方和下方添加一些空行以查看效果。
我注意到一件非常奇怪的事情是我必须在一个新的查询窗口中运行EXEC ErrorTesting
,而不是在同一窗口的底部突出显示它并运行……当我这样做时,行号一直在上升!不知道为什么会这样..
【讨论】:
【参考方案8】:关于这个问题的有用文章:
http://tomaslind.net/2013/10/15/line-numbers-in-t-sql-error-messages/
“如果您改为使用 Management Studio 生成脚本,则自动添加 USE dbname 语句以及 ANSI_NULLS 和 QUOTED_IDENTIFIER 的设置。删除这些语句(9 行)以获得正确的行号脚本窗口:"
【讨论】:
【参考方案9】:您可以像这样在 catch 块中获取错误消息和错误行:
'Ms Sql Server Error: - ' + ERROR_MESSAGE() + ' - Error occured at: ' + CONVERT(VARCHAR(20), ERROR_LINE())
【讨论】:
【参考方案10】:只需将以下代码添加到您的存储过程中,以“LINENO xx”表示绝对行起始号,其中“xx”是您在 SQL Mgt Studio 中打开 SP 时的实际行号
例如,
USE [Northwind]
GO
/****** Object: StoredProcedure [automate].[workorders_exceptions_generate] Script Date: 03/03/2021 8:49:23 AM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
/*
Here are some comments here
Which are white spaces
But the actual line after the "BEGIN" statement is 21
*/
CREATE PROCEDURE dbo.something
@ChildWOID varchar(30)
, @DontByPass bit = 0
, @BillingStatus varchar(30) = null OUTPUT
AS
BEGIN
LINENO 21
PRINT 'HELLO WORLD'
END
【讨论】:
以上是关于如何从错误消息中获取实际的存储过程行号?的主要内容,如果未能解决你的问题,请参考以下文章