Comment puis-je obtenir le numéro de ligne de procédure stockée réel à partir d'un message d'erreur?


111

Lorsque j'utilise SQL Server et qu'il y a une erreur, le message d'erreur donne un numéro de ligne qui n'a pas de corrélation avec les numéros de ligne dans la procédure stockée. Je suppose que la différence est due aux espaces blancs et aux commentaires, mais est-ce vraiment?

Comment puis-je relier ces deux ensembles de numéros de ligne l'un à l'autre? Si quelqu'un pouvait me donner au moins un indicateur dans la bonne direction, je l'apprécierais vraiment.

J'utilise SQL Server 2005.


1
Je pense que le numéro de ligne se rapporte au corps du proc. c'est à dire ignorer l'en-tête.
Martin Smith


Où se termine l'en-tête? Après le début qui suit la procédure de modification ... AS?
chama

Il semblait commencer à compter à partir de la create procligne dans mon test. Je suppose que vous voyez quelque chose de différent.
Martin Smith

1
Décrit dans ma réponse ici: stackoverflow.com/questions/2947173/…
gbn

Réponses:


113

IIRC, il commence à compter les lignes à partir du début du lot qui a créé ce proc. Cela signifie soit le début du script, soit la dernière instruction "GO" avant l'instruction create / alter proc.

Un moyen plus simple de voir cela consiste à extraire le texte réel utilisé par SQL Server lors de la création de l'objet. Basculez votre sortie en mode texte (CTRL-T avec les mappages de touches par défaut) et exécutez

sp_helptext proc_name

Copiez collez les résultats dans une fenêtre de script pour obtenir la coloration syntaxique, etc., et utilisez la fonction de ligne goto (CTRL-G je pense) pour accéder à la ligne d'erreur signalée.


14
Quand j'ai fait cela en mode Grid-Output, les numéros de ligne ont également
collé

2
@codeulike - Bon point, si vous utilisez la sortie Grid, le numéro de ligne correspondra au numéro de ligne, vous n'avez donc pas besoin d'utiliser CTRL + G. Mon seul problème avec la sortie Grid est qu'elle change les caractères TAB en un seul ESPACE, de sorte que vous perdez toute la mise en forme.
Rick

33

Par habitude je place LINENO 0directement après BEGINdans mes procédures stockées. Cela réinitialise le numéro de ligne - à zéro, dans ce cas. Ensuite, ajoutez simplement le numéro de ligne signalé par le message d'erreur au numéro de ligne dans SSMS où vous avez écrit LINENO 0et bingo - vous avez le numéro de ligne de l'erreur comme représenté dans la fenêtre de requête.


4
Pourquoi ne pas simplement mettre "LineNo X" où X = le numéro de ligne sur lequel vous mettez l'instruction, afin qu'il soit automatiquement ajouté au numéro de ligne signalé?
LarryBud

8

Si vous utilisez un bloc de capture et que vous avez utilisé un RAISERROR () pour toute validation de code dans le bloc Try, la ligne d'erreur est signalée là où se trouve le bloc de capture et non où l'erreur réelle s'est produite. Je l'ai utilisé comme ça pour clarifier cela.

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

6

En fait, cela Error_number()fonctionne très bien.

Cette fonction commence le décompte à partir de la dernière instruction GO (Batch Separator), donc si vous n'avez utilisé aucun espace Go et qu'elle affiche toujours un numéro de ligne erroné, ajoutez-y 7, comme dans la procédure stockée à la ligne numéro 7, le séparateur de lots est utilisé automatiquement. Donc, si vous utilisez sélectionnez Cast (Error_Number () + 7 as Int) comme [Error_Number] - vous obtiendrez la réponse souhaitée.


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'est-ce que c'était censé signifier?
underscore_d

4

Dans TSQL / Procédures stockées

Vous pouvez obtenir une erreur telle que:

Msg 206, niveau 16, état 2, procédure myproc, ligne 177 [Batch Start Line 7]

Cela signifie que l'erreur se trouve à la ligne 177 du lot. Pas 177 dans le SQL. Vous devriez voir sur quel numéro de ligne commence votre lot, dans mon cas [7], puis vous ajoutez cette valeur au numéro de ligne pour trouver quelle déclaration est erronée


2

vous pouvez utiliser ceci

CAST(ERROR_LINE() AS VARCHAR(50))

et si vous souhaitez créer un tableau du journal des erreurs, vous pouvez utiliser ceci:

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

4
Notez que ERROR_LINE () est uniquement disponible dans la partie CATCH d'un TRY / CATCH au sein de la procédure stockée. Le numéro de ligne qu'il signale est le même que celui que SQL Server renvoie si vous ne détectez pas l'erreur. Donc, bien que cela puisse être utile, cela n'aide pas à résoudre cette question.
Rick

1

La réponse longue: le numéro de ligne est compté à partir de l' CREATE PROCEDUREinstruction, plus toutes les lignes vides ou les lignes de commentaire que vous avez pu avoir au-dessus lorsque vous avez réellement exécuté l' CREATEinstruction, mais sans compter les lignes avant unGO instruction…

J'ai trouvé beaucoup plus facile de faire un proc stocké avec lequel jouer pour confirmer:

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

Une fois que vous l'avez créé, vous pouvez le changer ALTER PROCEDUREet ajouter des lignes vides au-dessus des commentaires et au-dessus et en dessous du premierGO instruction pour voir l'effet.

Une chose très étrange que j'ai remarquée était que je devais courir EXEC ErrorTestingdans une nouvelle fenêtre de requête au lieu de la mettre en surbrillance au bas de la même fenêtre et de courir… Quand j'ai fait ça, les numéros de ligne ont continué à augmenter! Je ne sais pas pourquoi cela s'est produit.


1

vous pouvez obtenir un message d'erreur et une ligne d'erreur dans le bloc catch comme ceci:

'Ms Sql Server Error: - ' + ERROR_MESSAGE() + ' - Error occured at: ' + CONVERT(VARCHAR(20),  ERROR_LINE())
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.