¿Cómo puedo obtener el número de línea del procedimiento almacenado real de un mensaje de error?

110

Cuando utilizo SQL Server y hay un error, el mensaje de error da un número de línea que no tiene correlación con los números de línea en el procedimiento almacenado. Supongo que la diferencia se debe a los espacios en blanco y los comentarios, pero ¿es realmente así?

¿Cómo puedo relacionar estos dos conjuntos de números de línea entre sí? Si alguien pudiera darme al menos un indicador en la dirección correcta, realmente lo agradecería.

Estoy usando SQL Server 2005.

chama
fuente
1
Creo que el número de línea se relaciona con el cuerpo del proceso. es decir, ignore el encabezado.
Martin Smith
Tal vez stackoverflow.com/questions/4550342/… le ayude.
John Saunders
¿Dónde termina el encabezado? Después del comienzo que sigue al procedimiento de alteración ... ¿AS?
chama
Pareció comenzar a contar desde la create proclínea en mi prueba. Supongo que estás viendo algo diferente.
Martin Smith
1
Descrito en mi respuesta aquí: stackoverflow.com/questions/2947173/…
gbn

Respuestas:

113

IIRC, comienza a contar líneas desde el inicio del lote que creó ese proceso. Eso significa el inicio del script o la última instrucción "GO" antes de la instrucción create / alter proc.

Una forma más sencilla de verlo es extraer el texto real que utilizó SQL Server al crear el objeto. Cambie su salida al modo de texto (CTRL-T con las asignaciones de teclas predeterminadas) y ejecute

sp_helptext proc_name

Copie y pegue los resultados en una ventana de secuencia de comandos para resaltar la sintaxis, etc., y use la función ir a la línea (CTRL-G, creo) para ir a la línea de error informada.

Almiar
fuente
14
Cuando hice esto en el modo Grid-Output, también pegó los números de línea
codeulike
2
@codeulike: buen punto, si usa la salida de cuadrícula, el número de fila coincidirá con el número de línea, por lo que no necesita usar CTRL + G. Mi único problema con la salida de Grid es que cambia los caracteres TAB a un solo ESPACIO, por lo que pierde todo el formato.
Rick
32

Por costumbre, coloco LINENO 0directamente después BEGINen mis procedimientos almacenados. Esto restablece el número de línea, a cero, en este caso. Luego, simplemente agregue el número de línea informado por el mensaje de error al número de línea en SSMS donde escribió LINENO 0y bingo; tiene el número de línea del error como se representa en la ventana de consulta.

Vorlic
fuente
4
¿Por qué no simplemente poner "LineNo X" donde X = el número de línea en el que puso la declaración, para que se agregue automáticamente al número de línea informado?
LarryBud
8

Si usa un bloque de captura y utilizó un RAISERROR () para cualquier validación de código dentro del bloque de prueba, la línea de error se informa donde está el bloque de captura y no donde ocurrió el error real. Lo usé así para aclarar eso.

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
Eduardo
fuente
6

En realidad esto Error_number() funciona muy bien.

Esta función comienza los recuentos desde la última instrucción GO (Separador de lotes), por lo que si no ha utilizado ningún espacio Go y todavía muestra un número de línea incorrecto, agregue 7, como en el procedimiento almacenado en la línea número 7, el separador de lotes se utiliza automáticamente. Por lo tanto, si utiliza Cast (Error_Number () + 7 como Int) como [Error_Number], obtendrá la respuesta deseada.

usuario2294834
fuente
1
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.- ¿Qué se suponía que significaba esto?
underscore_d
4

En TSQL / Procedimientos almacenados

Puede recibir un error como:

Msg 206, nivel 16, estado 2, procedimiento myproc, línea 177 [línea de inicio de lote 7]

Esto significa que el error está en la línea 177 del lote. No 177 en el SQL. Debería ver en qué número de línea comienza su lote, en mi caso [7], y luego agrega ese valor al número de línea para encontrar qué declaración es incorrecta

jasttim
fuente
2

puedes usar esto

CAST(ERROR_LINE() AS VARCHAR(50))

y si desea hacer una tabla de registro de errores, puede usar esto:

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())
HAJJAJ
fuente
4
Tenga en cuenta que ERROR_LINE () solo está disponible en la parte CATCH de un TRY / CATCH dentro del procedimiento almacenado. El número de línea que informa es el mismo que devuelve SQL Server si no detecta el error. Entonces, si bien eso puede ser útil, no ayuda a resolver esta pregunta.
Rick
1

La respuesta larga: el número de línea se cuenta a partir de la CREATE PROCEDUREdeclaración, más cualquier línea en blanco o línea de comentario que pueda haber tenido arriba cuando realmente ejecutó la CREATEdeclaración, pero sin contar las líneas antes de una GOdeclaración ...

Me pareció mucho más fácil hacer un proceso almacenado para jugar y confirmar:

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

Una vez que lo haya creado, puede cambiarlo ALTER PROCEDUREy agregar algunas líneas en blanco encima de los comentarios y arriba y debajo de la primeraGO declaración para ver el efecto.

Una cosa muy extraña que noté fue que tenía que correr EXEC ErrorTesting en una nueva ventana de consulta en lugar de resaltarla en la parte inferior de la misma ventana y ejecutar… ¡Cuando hice eso, los números de línea siguieron aumentando! No estoy seguro de por qué sucedió eso ...

Andy Raddatz
fuente
1

puede obtener un mensaje de error y una línea de error en el bloque de captura como este:

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