Auffinden der Parameter einer gespeicherten Prozedur nach der Ausführung

7

Ich wurde gebeten, ein Berechtigungsproblem mit einer gespeicherten Prozedur zu identifizieren. Diese gespeicherte Prozedur verhält sich auf zwei Arten, je nachdem, welche Werte für ihre Parameter verwendet werden.

exec ps_my_stored_procedure @a=1, @b=2, @c=3

wird ganz anders gehandhabt als

exec ps_my_stored_procedure @a=5, @b=7, @c=0

Man könnte sagen, das ps_my_stored_procedureist logisch in zwei völlig getrennte Prozesse unterteilt.

Mit dm_exec_procedure_statsund dm_exec_query_statskann ich den Ausführungsplan finden, der die SQL der verwendeten gespeicherten Prozedur zeigt. Ich konnte jedoch nicht wiederherstellen, wie die Parameter definiert wurden und mit welchen Werten.

Ist es möglich, mit dm_exec_procedure_statsund dm_exec_query_statsund anderen Verwaltungsansichten die Ausführung der gespeicherten Prozedur zu rekonstruieren, die die für ihre Parameter verwendeten Werte anzeigt?

Was ich wirklich gerne im Cache finden würde, ist die tatsächliche Ausführung der gespeicherten Prozedur, damit ich sie so ausführen kann, wie sie EXECUTE AS LOGIN = 'someone'zur Behebung der Berechtigungsprobleme verwendet wird

Craig Efrein
quelle

Antworten:

5

Wenn Sie über den Ausführungsplan verfügen, können Sie ihn als XML anzeigen und nach kompilierten Parameterwerten suchen

Dies ist beispielsweise ein tatsächlicher Ausschnitt eines Ausführungsplans aus einer der Abfragen in meinem Plan-Cache:

   <ParameterList>
      <ColumnReference Column="@P69" ParameterCompiledValue="'2015-06-10 00:00:00.0000000'" />
       <ColumnReference Column="@P68" ParameterCompiledValue="'somestring'" />
   </ParameterList>

Wenn Ihre Pläne wiederverwendet werden, wird der Wert zum Zeitpunkt der Kompilierung angezeigt.

Tom V - versuchen Sie topanswers.xyz
quelle
11

Ich verwende häufig die folgende Abfrage von http://www.sommarskog.se/query-plan-mysteries.html#otherreasons , um die Sniffed-Werte zurückzugeben. Eine andere Möglichkeit besteht darin, den Plan im SQL Sentry Plan Explorer zu öffnen und die Registerkarte Parameter auszuwählen. Sowohl die XML-Methode als auch die Plan-Explorer-Methode zeigen die Laufzeitwerte an, sofern Sie den tatsächlichen Ausführungsplan anzeigen.

DECLARE @dbname    nvarchar(256),
        @procname  nvarchar(256)

SELECT @dbname  = '',
       @procname = '' -- enter proc name

; WITH basedata AS (
   SELECT qs.plan_handle,
            qs.statement_start_offset/2 AS stmt_start,
          qs.statement_end_offset/2 AS stmt_end,
          est.encrypted AS isencrypted, est.text AS sqltext,
          epa.value AS set_options, qp.query_plan,
          charindex('<ParameterList>', qp.query_plan) + len('<ParameterList>')
             AS paramstart,
          charindex('</ParameterList>', qp.query_plan) AS paramend
   FROM   sys.dm_exec_query_stats qs
   CROSS  APPLY sys.dm_exec_sql_text(qs.sql_handle) est
   CROSS  APPLY sys.dm_exec_text_query_plan(qs.plan_handle,
                                            qs.statement_start_offset,
                                            qs.statement_end_offset) qp
   CROSS  APPLY sys.dm_exec_plan_attributes(qs.plan_handle) epa
   WHERE  est.objectid  = object_id (@procname)
     AND  est.dbid      = db_id(@dbname)
     AND  epa.attribute = 'set_options'
), next_level AS (
   SELECT plan_handle,stmt_start, set_options, query_plan,
          CASE WHEN isencrypted = 1 THEN '-- ENCRYPTED'
               WHEN stmt_start >= 0
               THEN substring(sqltext, stmt_start + 1,
                              CASE stmt_end
                                   WHEN 0 THEN datalength(sqltext)
                                   ELSE stmt_end - stmt_start + 1
                              END)
          END AS Statement,
          CASE WHEN paramend > paramstart
               THEN CAST (substring(query_plan, paramstart,
                                   paramend - paramstart) AS xml)
          END AS params
   FROM   basedata
)

SELECT set_options AS [SET]
        , n.stmt_start AS Pos
        , n.Statement
       , CR.c.value('@Column', 'nvarchar(128)') AS Parameter
       , CR.c.value('@ParameterCompiledValue', 'nvarchar(128)') AS [Sniffed Value]
       , CAST (query_plan AS xml) AS [Query plan]
       , n.plan_handle
FROM   next_level n
CROSS  APPLY   
        n.params.nodes('ColumnReference') AS CR(c)
ORDER  BY n.set_options, n.stmt_start, Parameter
Pixeliert
quelle
Dies funktioniert nicht für SQL 2016 SP-Parameter, da n.params.nodesXML kein ColumnReferenceElement enthält . Es enthält nur <ScalarOperator ScalarString="(0)"> <Const ConstValue="(0)" /> </ScalarOperator> <ScalarOperator ScalarString="NULL"> <Const ConstValue="NULL" /> </ScalarOperator>Folgendes : Funktioniert auch 2012 nicht. Was fehlt?
Ajeh