web-dev-qa-db-fra.com

Comment déboguer des procédures stockées avec des instructions d'impression?

J'essaie de déboguer des procédures stockées dans SQL Server Management Studio 2008. Je souhaite insérer des instructions d'impression pour tester des instructions IF erronées.

Afin de faire le débogage, j'ai essayé d'utiliser la commande PRINT '5'.

J'ai essayé d'utiliser le RAISERROR comme 'RAISERROR (N'Start',10,1) WITH NOWAIT'.

Mais ceux-ci ne montraient aucune impression, mais uniquement le jeu de résultats. Le message dit simplement 1 row affected.

J'ai essayé d'écrire le code comme ça (peut-être que c'est une approche incorrecte):

SET NOCOUNT ON         
RAISERROR (N'Start',10,1) WITH NOWAIT    
DECLARE @DocHandle INT        
DECLARE @PageSize INT, @PageIndex INT, @TOTL_CONT NUMERIC(5,0), @Paging BIT        
DECLARE @Type INT, @Search varchar(20) , @ORDE nVARCHAR(50), @SORT_ID nVARCHAR(50) 
DECLARE @CreatedOn varchar(25), @SystemGenerate bit   

Quel est le meilleur moyen d'utiliser des instructions d'impression pour déboguer une procédure stockée?

33
Art F

Si vous utilisez MSSQL Server management studio, les instructions d'impression seront imprimées sous l'onglet Messages et non sous l'onglet Résultats.

enter image description here

Les déclarations imprimées y apparaîtront.

26
Kevin Kunderman

Avant d’arriver à ma réponse répétée; J'avoue que la seule réponse que j'accepterais ici est la suivante: ne par KM. ci-dessus. J'ai voté contre les autres réponses parce qu'aucune d'entre elles n'avait répondu à la question posée ou qu'elles n'étaient pas adéquates. La sortie PRINT apparaît bien dans la fenêtre Message, mais ce n’est pas du tout ce qui a été demandé.

Pourquoi la sortie de l'instruction PRINT n'est-elle pas affichée lors de l'exécution de la procédure stockée?
La version abrégée de cette réponse indique que vous envoyez l'exécution de votre sproc au serveur SQL et que celui-ci ne répondra pas avant la fin de la transaction. Voici une meilleure réponse à cette lien externe .

  • Pour encore plus d'opinions/observations, concentrez votre attention sur ceci SO post ici .
  • Regardez spécifiquement ceci réponse du même message de Phil_factor (Ha ha! Love the SQL humor)
  • En ce qui concerne la suggestion d’utiliser RAISERROR WITH NOWAIT, regardez ceci réponse du même message de JimCarden

Ne faites pas ces choses

  1. Certaines personnes ont l’impression de pouvoir utiliser une instruction GO après leur instruction PRINT, mais vous ne POUVEZ PAS utiliser l’instruction GO INSIDE d’un sproc. Donc, cette solution est hors.
  2. Je ne recommande pas de sélectionner vos instructions d'impression, car cela va bouleverser votre jeu de résultats avec un non-sens et si votre sproc est censé être consommé par un programme plus tard, vous devrez alors savoir quels jeux de résultats doivent être ignorés lors de la mise en boucle. à travers les résultats de votre lecteur de données. C'est juste une mauvaise idée, alors ne le faites pas.
  3. Un autre problème avec SELECT-ING dans vos relevés d'impression est qu'ils ne s'affichent pas toujours immédiatement. J'ai eu différentes expériences avec cela pour différentes exécutions, alors ne vous attendez pas à une quelconque cohérence avec cette méthodologie.

Alternative à PRINT à l'intérieur d'une procédure stockée
C’est vraiment une sorte de travail fastidieux à mon avis, car la syntaxe est déroutante dans le contexte dans lequel elle est utilisée, mais qui sait peut-être qu’elle sera mise à jour ultérieurement par Microsoft. Je n'aime pas l'idée de générer une erreur dans le seul but d'imprimer des informations de débogage ...

Il semble que la seule solution à ce problème consiste à utiliser, comme cela a été expliqué à de nombreuses reprises déjà avec RAISERROR WITH NOWAIT. Je donne un exemple et souligne un petit problème avec cette approche:

ALTER
--CREATE 
    PROCEDURE [dbo].[PrintVsRaiseErrorSprocExample]
AS
BEGIN
    SET NOCOUNT ON;

    -- This will print immediately
    RAISERROR ('RE Start', 0, 1) WITH NOWAIT
    SELECT 1;

    -- Five second delay to simulate lengthy execution
    WAITFOR DELAY '00:00:05'

    -- This will print after the five second delay
    RAISERROR ('RE End', 0, 1) WITH NOWAIT
    SELECT 2;
END

GO

EXEC [dbo].[PrintVsRaiseErrorSprocExample]

Les deux résultats des instructions SELECT ne s'afficheront qu'une fois l'exécution terminée et les instructions print s'afficheront dans l'ordre indiqué ci-dessus.

Problème potentiel de cette approche
Supposons que vos instructions PRINT et RAISERROR se succèdent, puis qu’elles s’impriment. Je suis sûr que cela a quelque chose à voir avec la mise en mémoire tampon, mais sachez que cela peut arriver.

ALTER
--CREATE 
    PROCEDURE [dbo].[PrintVsRaiseErrorSprocExample2]
AS
BEGIN
    SET NOCOUNT ON;

    -- Both the PRINT and RAISERROR statements will show
    PRINT 'P Start';
    RAISERROR ('RE Start', 0, 1) WITH NOWAIT
    SELECT 1;

    WAITFOR DELAY '00:00:05'

    -- Both the PRINT and RAISERROR statements will show
    PRINT 'P End'
    RAISERROR ('RE End', 0, 1) WITH NOWAIT
    SELECT 2;
END

GO

EXEC [dbo].[PrintVsRaiseErrorSprocExample2]

Par conséquent, le travail à effectuer ici consiste à ne pas utiliser à la fois PRINT et RAISERROR, il suffit de choisir l’un sur l’autre. Si vous souhaitez que votre sortie apparaisse pendant l'exécution d'un sproc, utilisez RAISERROR WITH NOWAIT.

13
dyslexicanaboko

Voici un exemple d'utilisation des instructions d'impression. Ils devraient apparaître sous l'onglet des messages en tant que personne précédente indiquée.

    Declare @TestVar int = 5;

    print 'this is a test message';
    print @TestVar;
    print 'test-' + Convert(varchar(50), @TestVar);

Print Messages

13
cmartin

essayez d'utiliser:

RAISERROR('your message here!!!',0,1) WITH NOWAIT

vous pouvez également essayer de passer à "Résultats en texte", il ne s'agit que de quelques icônes à droite de "Exécuter" dans la barre d'outils par défaut.

Avec les deux éléments ci-dessus en place et que vous ne voyez toujours pas les messages, assurez-vous que vous exécutez la même version serveur/base de données/propriétaire de la procédure que vous modifiez. Assurez-vous que vous exécutez la commande RAISERROR, faites-en la première commande de la procédure.

Si tout échoue, vous pouvez créer une table:

create table temp_log (RowID int identity(1,1) primary key not null
                      , MessageValue varchar(255))

puis:

INSERT INTO temp_log VALUES ('Your message here')

puis, après avoir exécuté la procédure (sans restauration), seulement select la table.

11
KM.