如何从错误消息中获取实际的存储过程行号?

时间:2010-12-30 19:30:44

标签: sql sql-server-2005

当我使用Sql Server并且出现错误时,错误消息会提供与存储过程中的行号无关的行号。我认为差异是由于空格和注释,但它真的是吗?

如何将这两组行号相互关联?如果有人能给我一个指向正确方向的指针,我真的很感激。

我正在使用sql server 2005。

TIA!

10 个答案:

答案 0 :(得分:105)

IIRC,它开始计算从创建该proc的批处理开始的行。这意味着要么是脚本的开头,要么是创建/更改proc语句之前的最后一个“GO”语句。

更简单的方法是拉取SQL Server在创建对象时使用的实际文本。将输出切换到文本模式(使用默认键映射的CTRL-T)并运行

sp_helptext proc_name

将结果复制粘贴到脚本窗口以获取语法突出显示等,并使用goto行函数(我认为是CTRL-G)转到报告的错误行。

答案 1 :(得分:24)

出于习惯,我将 List<Article> model = new List<Article>(); foreach (var keyword in keywords) { model.AddRange(articles.Where(a => a.Title.Contains(keyword) || a.Description.Contains(keyword))); } 直接放在LINENO 0的存储过程中。在这种情况下,这会将行号重置为零。然后,只需将错误消息报告的行号添加到您编写BEGIN和bingo的SSMS中的行号 - 您将在查询窗口中显示错误的行号。

答案 2 :(得分:7)

实际上这个Error_number()效果很好。

此函数从上一个GO(批处理分隔符)语句开始计数,因此如果您没有使用任何Go空格并且它仍显示错误的行号 - 则向其添加7,如第7行中的存储过程批处理分隔符自动使用。所以,如果你使用 选择Cast(Error_Number()+ 7作为Int)作为[Error_Number] - 您将得到所需的答案。

答案 3 :(得分:5)

如果使用Catch Block并使用RAISERROR()在Try Block中进行任何代码验证,则会报告错误行,而Catch Block位于此处,而不是发生实际错误的位置。我这样用它来清除它。

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

答案 4 :(得分:2)

你可以用这个

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())

答案 5 :(得分:2)

有关此问题的有用文章:

http://tomaslind.net/2013/10/15/line-numbers-in-t-sql-error-messages/

“如果您改为使用Management Studio生成脚本,则会自动添加USE dbname 语句以及ANSI_NULLS和QUOTED_IDENTIFIER的设置。删除这些语句(9行)以获取正确的行号脚本窗口:“

答案 6 :(得分:1)

您可以在catch块中获取错误消息和错误行,如下所示:

'Ms Sql Server Error: - ' + ERROR_MESSAGE() + ' - Error occured at: ' + CONVERT(VARCHAR(20),  ERROR_LINE())

答案 7 :(得分:1)

在TSQL /存储过程中

您可能会收到以下错误消息:

  

信息206,级别16,状态2,过程myproc,第177行[批处理开始第7行]

这意味着该错误在批处理中的第177行上。在SQL中不是177。在我的案例中,您应该看到批处理从哪个行号开始[7],然后将该值添加到该行号中以查找错误的语句

答案 8 :(得分:0)

答案很长:行号从CREATE PROCEDURE语句计算,加上实际运行CREATE语句时可能在其上方的任何空白行或注释行,但不计算任何GO陈述之前的行......

我发现使存储过程更容易进行确认:

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并在评论上方以及第一个GO语句的上方和下方添加一些空行以查看效果。

我注意到的一件非常奇怪的事情是,我必须在新的查询窗口中运行EXEC ErrorTesting,而不是在同一窗口的底部突出显示并运行...当我这样做时,行号不断上升!不知道为什么会发生这种情况..

答案 9 :(得分:0)

只需将以下代码添加到您的存储过程中,以使用“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