Est-il possible d'enregistrer des valeurs de paramètres entrantes dans un appel de procédure lors du traçage dans SQL Server Profiler?

13

À l'aide de SQL Server Profiler (je suis sur SQL Server 2012), j'essaie de générer une trace utile qui montre les valeurs des paramètres, pas seulement le SQL avec des noms de variables. La procédure stockée parcourt une quantité brute de données d'inventaire pour générer des résultats extrêmement précieux, et j'essaie de documenter le comportement existant, afin que je puisse le tester à l'unité, le définir exactement, puis le refactoriser en quelque chose de sain.

J'ai une procédure stockée qui exécute une sous-procédure de 54 paramètres, à l'intérieur d'une boucle où la procédure stockée crée un curseur puis fait une boucle while. Voici une vue simplifiée:

CREATE PROCEDURE 
   [dbo].[OuterProcedure]       
   (  @ProductCode varchar(8),          
     -- 41 more parameters omitted
   )
AS            
  SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED   
  SET NOCOUNT ON           
 DECLARE @AboutFourHundredLocalvariables -- omit about 400 local variable declarations.
 -- OMIT ABOUT 10 temporary table declarations.
 DECLARE  aCursor CURSOR FAST_FORWARD FOR         
   SELECT [ID],bkno,  -- about 40 fields omitted.
              FROM vwVeryComplexViewThatDoesALotOfVeryBrutalJoins         
              WHERE  (about_80_boolean_expressions AND omitted_here)
        ORDER BY some,keys,like,this

OPEN aCursor          
FETCH NEXT FROM aCursor /* Get First Record */         
    INTO @ID, @about_40_fields,.... 
WHILE (@@FETCH_STATUS = 0) AND         
          ( @About80MoreBooleanExpressionsHere)  
BEGIN   /* 1 */            
     -- about 700 lines of logic, math and if-parameter-this-then-that
     -- stuff omitted
            EXEC  @ConsiderItem = 
                      InnerProcedureCallWithinLoop
                                            @from_locn,        
                        @About53PARAMSOMITTED,
                                                ...

    FETCH NEXT FROM CurInventory /* Get Next Record */       
       INTO @ID,@MoreStuff,...    
END                   
CLOSE CurInventory          
DEALLOCATE CurInventory        

Comment puis-je obtenir une trace pour me montrer toutes les valeurs de paramètres transmises à InnerProcedureCallWithinLoop? Il y a 54 paramètres. Dois-je écrire essentiellement "54 lignes de debug-printfs" dans mon SQL ou puis-je vider toutes les valeurs des paramètres d'un appel de procédure tout en faisant un suivi SQL?

Quand j'obtiens une trace maintenant, j'obtiens cette sortie:

EXEC  @ConsiderItem = InnerProcedureCallWithinLoop  @from_locn,        
                        @About53ParmsOmitted

Ce que je voudrais savoir est que @from_locn = 1et @About53ParmsOmitted = 'hello world'et ainsi de suite.

Cela ne me dit pas la valeur réelle du paramètre @from_locn. Dans le cas de ce premier paramètre, il est transmis à ma procédure stockée de niveau supérieur, donc je sais que c'est 0 ou 1, selon le cas. Cependant, environ 40 des 43 paramètres de cette procédure interne proviennent de l' FETCH NEXT FROM aCursoropération à l'intérieur d'une WHILEboucle.

En ce moment, le traçage me dit combien de fois InnerProcedureCallWithinLoopest invoqué et combien de temps chacune a pris, mais pas quelles étaient les valeurs des paramètres de cet appel. Si je pouvais en quelque sorte obtenir des "scripts SQL autonomes exécutables" qui reproduisent certains cas de coin que je trouve dans mon code, tout en parcourant ces scripts, en configurant ces fonctions brutes (je sais, 54 paramètres, c'est vraiment brut, mais je n'ai pas écrit eux!) pourrait me prendre une heure à taper juste pour construire un script SQL qui me permet d'invoquer moi-même ce cas de coin, en dehors de ce gros grognement gargantuesque de procédures stockées SQL Server.

Tout cela fait partie d'un effort pour explorer une expression SQL et créer des scripts qui peuvent sonder ces procédures stockées complexes.

Mise à jour J'ai trouvé une option d'enregistrement "Output Param" RPC, mais pas une option d'enregistrement "RPC IN PARAM".

Warren P
la source
Ce ne sont pas seulement les 54 paramètres qui sont grossiers :-) Tout ça en boucle pour appeler un curseur. C'est dégoûtant :-) Avez-vous joué avec l'explorateur de plans de SQL Sentry? Vous pouvez utiliser la version gratuite ou utiliser un essai de la version complète et cela peut vous aider si vous avez un appel avec tous les paramètres - sqlsentry.net/plan-explorer/sql-server-query-view.asp
Mike Walsh
Pouvez-vous nous dire quels événements vous capturez?
Mike Walsh
2
La seule fois où le profileur capture ces données (je pense), c'est quand vous les appelez? Essayez de mettre en place une table d'audit avec tous ces paramètres, et faites juste une insertion avant de boucler votre curseur?
jcolebrand
RPC: Terminé affiche les valeurs des paramètres mais au niveau externe.
Mike Walsh
3
+1 pour la question, en récompense de votre douleur. Si je le pouvais, je ferais +1 à nouveau pour avoir posté la question sans explications.
Mark Storey-Smith

Réponses:

8

Je vais mordre la balle et vous dire qu'une telle trace ne peut pas être établie, car ce n'est pas le but [perçu] des traces. Je l'ai toujours fait de cette façon:


            TANT QUE (@@ FETCH_STATUS = 0) ET (@ About80MoreBooleanExpressionsHere)
COMMENCEZ / * 1 * /
    - environ 700 lignes de logique, mathématiques et if-parameter-this-then-that
    - stuff omis
      INSERT InnerProcedureCallWithinLoop__TraceTable
              VALUES (@from_locn, @ About53PARAMSOMITTED

      EXEC @ConsiderItem =
            InnerProcedureCallWithinLoop
                  @from_locn,
                        @ About53PARAMSOMITTED,
...

Si je sais qu'il n'est appelé que depuis un seul endroit. Sinon, je le fais dans l'appelé au lieu de l'appelant.

ALTER PROC InnerProcedureCallWithinLoop
    @from_locn int,
    @About53PARAMSOMITTED ...
AS
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
SET NOCOUNT ON;
INSERT InnerProcedureCallWithinLoop__TraceTable VALUES (@from_locn, @prm2, @prm3....
--- rest of proc

Ceci est évidemment différent de l'utilisation d'une trace, qui est capable de capturer des événements même s'ils ont commencé et ne se sont jamais terminés (paramètres défectueux, transactions annulées). Si tel est votre problème, vous devez consulter le CLR ou les méthodes de messagerie pour externaliser la sortie capturée.

孔夫子
la source
C'est ce que je pensais.
Warren P