@@ -210,6 +210,8 @@ CREATE TABLE ##bou_BlitzCacheProcs (
210210 estimated_rows FLOAT ,
211211 is_bad_estimate BIT ,
212212 is_paul_white_electric BIT ,
213+ implicit_conversion_info XML ,
214+ cached_execution_parameters XML ,
213215 SetOptions VARCHAR (MAX ),
214216 Warnings VARCHAR (MAX )
215217 );
@@ -891,6 +893,8 @@ BEGIN
891893 estimated_rows FLOAT ,
892894 is_bad_estimate BIT ,
893895 is_paul_white_electric BIT ,
896+ implicit_conversion_info XML ,
897+ cached_execution_parameters XML ,
894898 SetOptions VARCHAR (MAX ),
895899 Warnings VARCHAR (MAX )
896900 );
@@ -1017,6 +1021,9 @@ IF OBJECT_ID ('tempdb..#checkversion') IS NOT NULL
10171021IF OBJECT_ID (' tempdb..#configuration' ) IS NOT NULL
10181022 DROP TABLE #configuration ;
10191023
1024+ IF OBJECT_ID (' tempdb..#stored_proc_info' ) IS NOT NULL
1025+ DROP TABLE #stored_proc_info;
1026+
10201027CREATE TABLE #only_query_hashes (
10211028 query_hash BINARY (8 )
10221029);
@@ -1056,6 +1063,19 @@ CREATE TABLE #configuration (
10561063 value DECIMAL (38 ,0 )
10571064);
10581065
1066+ CREATE TABLE #stored_proc_info
1067+ (
1068+ SPID INT ,
1069+ QueryHash BINARY (8 ),
1070+ variable_name NVARCHAR (128 ),
1071+ variable_datatype NVARCHAR (128 ),
1072+ compile_time_value NVARCHAR (128 ),
1073+ proc_name NVARCHAR (300 ),
1074+ column_name NVARCHAR (128 ),
1075+ converted_to NVARCHAR (128 )
1076+ );
1077+
1078+
10591079RAISERROR (N ' Checking plan cache age' , 0 , 1 ) WITH NOWAIT ;
10601080WITH x AS (
10611081SELECT SUM (CASE WHEN DATEDIFF (HOUR, deqs .creation_time , SYSDATETIME ()) <= 24 THEN 1 ELSE 0 END ) AS [plans_24],
@@ -1102,7 +1122,6 @@ WHERE cp.usecounts = 1
11021122OPTION (RECOMPILE ) ;
11031123
11041124
1105-
11061125SET @OnlySqlHandles = LTRIM (RTRIM (@OnlySqlHandles)) ;
11071126SET @OnlyQueryHashes = LTRIM (RTRIM (@OnlyQueryHashes)) ;
11081127SET @IgnoreQueryHashes = LTRIM (RTRIM (@IgnoreQueryHashes)) ;
@@ -2826,6 +2845,164 @@ ON ipwe.SqlHandle = b.SqlHandle
28262845WHERE b .SPID = @@SPID
28272846OPTION (RECOMPILE );
28282847
2848+ IF EXISTS ( SELECT 1
2849+ FROM ##bou_BlitzCacheProcs AS bbcp
2850+ WHERE bbcp .implicit_conversions = 1
2851+ OR bbcp .QueryType LIKE ' Procedure or Function:%' )
2852+ BEGIN
2853+
2854+ RAISERROR (N ' Getting information about implicit conversions and stored proc parameters' , 0 , 1 ) WITH NOWAIT ;
2855+
2856+ WITH XMLNAMESPACES ( ' http://schemas.microsoft.com/sqlserver/2004/07/showplan' AS p )
2857+ , variables_types
2858+ AS ( SELECT qp .QueryHash ,
2859+ qp .SqlHandle ,
2860+ SUBSTRING (b .QueryType , CHARINDEX (' [' , b .QueryType ), LEN (b .QueryType ) - CHARINDEX (' [' , b .QueryType )) AS proc_name,
2861+ q .n .value (' @Column' , ' NVARCHAR(128)' ) AS variable_name,
2862+ q .n .value (' @ParameterDataType' , ' NVARCHAR(128)' ) AS variable_datatype,
2863+ q .n .value (' @ParameterCompiledValue' , ' NVARCHAR(1000)' ) AS compile_time_value
2864+ FROM #query_plan AS qp
2865+ JOIN ##bou_BlitzCacheProcs AS b
2866+ ON b .QueryHash = qp .QueryHash
2867+ CROSS APPLY qp .query_plan .nodes (' //p:QueryPlan/p:ParameterList/p:ColumnReference' ) AS q(n)
2868+ WHERE qp .QueryHash IS NOT NULL
2869+ AND b .implicit_conversions = 1 ),
2870+ convert_implicit
2871+ AS ( SELECT qp .QueryHash ,
2872+ qp .SqlHandle ,
2873+ qq .c .value (' @Expression' , ' NVARCHAR(128)' ) AS expression,
2874+ SUBSTRING (
2875+ qq .c .value (' @Expression' , ' NVARCHAR(128)' ), -- Original Expression
2876+ CHARINDEX (' @' , qq .c .value (' @Expression' , ' NVARCHAR(128)' )), -- Charindex of @+1
2877+ CHARINDEX (' ]' ,
2878+ qq .c .value (' @Expression' , ' NVARCHAR(128)' ), -- Charindex of end bracket
2879+ CHARINDEX (' @' , qq .c .value (' @Expression' , ' NVARCHAR(128)' )) + 1 -- Starting at the Charindex of the @ +1
2880+ ) - CHARINDEX (' @' , qq .c .value (' @Expression' , ' NVARCHAR(128)' ))) AS variable_name,
2881+ SUBSTRING (
2882+ qq .c .value (' @Expression' , ' NVARCHAR(128)' ), -- Original Expression
2883+ CHARINDEX (' ].[' , qq .c .value (' @Expression' , ' NVARCHAR(128)' )) + 3 , -- Charindex of ].[ + 3
2884+ CHARINDEX (' ]' ,
2885+ qq .c .value (' @Expression' , ' NVARCHAR(128)' ), -- Charindex of end bracket
2886+ CHARINDEX (' ].[' , qq .c .value (' @Expression' , ' NVARCHAR(128)' )) + 3 -- Starting at the Charindex of ].[ + 3
2887+ ) - CHARINDEX (' ].[' , qq .c .value (' @Expression' , ' NVARCHAR(128)' )) - 3 ) AS column_name,
2888+ SUBSTRING (
2889+ qq .c .value (' @Expression' , ' NVARCHAR(128)' ), -- Original Expression
2890+ CHARINDEX (' (' , qq .c .value (' @Expression' , ' NVARCHAR(128)' )) + 1 , -- Charindex of ( + 1
2891+ CHARINDEX (' ,' ,
2892+ qq .c .value (' @Expression' , ' NVARCHAR(128)' ), -- Charindex of comma
2893+ CHARINDEX (' (' , qq .c .value (' @Expression' , ' NVARCHAR(128)' )) + 1 -- Starting at the Charindex of ( + 1
2894+ ) - CHARINDEX (' (' , qq .c .value (' @Expression' , ' NVARCHAR(128)' )) - 1 ) AS converted_to
2895+ FROM #query_plan AS qp
2896+ JOIN ##bou_BlitzCacheProcs AS b
2897+ ON b .QueryHash = qp .QueryHash
2898+ CROSS APPLY qp .query_plan .nodes (' //p:QueryPlan/p:Warnings/p:PlanAffectingConvert' ) AS qq(c)
2899+ WHERE qq .c .exist(' @ConvertIssue[.="Seek Plan"]' ) = 1
2900+ AND qp .QueryHash IS NOT NULL
2901+ AND b .implicit_conversions = 1 )
2902+ INSERT #stored_proc_info ( SPID, QueryHash, variable_name, variable_datatype, compile_time_value, proc_name, column_name, converted_to )
2903+ SELECT @@SPID ,
2904+ vt .QueryHash ,
2905+ vt .variable_name ,
2906+ vt .variable_datatype ,
2907+ vt .compile_time_value ,
2908+ vt .proc_name ,
2909+ ci .column_name ,
2910+ ci .converted_to
2911+ FROM variables_types AS vt
2912+ JOIN convert_implicit AS ci
2913+ ON ci .variable_name = vt .variable_name
2914+ AND ci .QueryHash = vt .QueryHash
2915+ OPTION (RECOMPILE );
2916+
2917+ WITH precheck AS (
2918+ SELECT spi .SPID ,
2919+ spi .QueryHash ,
2920+ spi .proc_name ,
2921+ CONVERT (XML ,
2922+ ' <?ClickMe -- '
2923+ + CHAR (10 )
2924+ + ' The stored procedure '
2925+ + spi .proc_name
2926+ + ' had the following implicit conversions: '
2927+ + CHAR (10 )
2928+ + STUFF ((
2929+ SELECT DISTINCT
2930+ CHAR (10 )
2931+ + ' The variable '
2932+ + spi2 .variable_name
2933+ + ' has a data type of '
2934+ + spi2 .variable_datatype
2935+ + ' which caused implicit conversion on the column '
2936+ + spi2 .column_name
2937+ FROM #stored_proc_info AS spi2
2938+ WHERE spi .QueryHash = spi2 .QueryHash
2939+ FOR XML PATH (N ' ' ), TYPE ).value (N ' .[1]' , N ' NVARCHAR(MAX)' ), 1 , 1 , N ' ' )
2940+ + CHAR (10 )
2941+ + ' -- ?>'
2942+ ) AS implicit_conversion_info,
2943+ CONVERT (XML ,
2944+ ' <?ClickMe -- '
2945+ + CHAR (10 )
2946+ + ' This statement '
2947+ + ' had the following implicit conversions: '
2948+ + CHAR (10 )
2949+ + STUFF ((
2950+ SELECT DISTINCT
2951+ CHAR (10 )
2952+ + ' The variable '
2953+ + spi2 .variable_name
2954+ + ' has a data type of '
2955+ + spi2 .variable_datatype
2956+ + ' which caused implicit conversion on the column '
2957+ + spi2 .column_name
2958+ FROM #stored_proc_info AS spi2
2959+ WHERE spi .QueryHash = spi2 .QueryHash
2960+ FOR XML PATH (N ' ' ), TYPE ).value (N ' .[1]' , N ' NVARCHAR(MAX)' ), 1 , 1 , N ' ' )
2961+ + CHAR (10 )
2962+ + ' -- ?>'
2963+ ) AS implicit_conversion_info_statement,
2964+ CONVERT (XML ,
2965+ ' <?ClickMe -- '
2966+ + CHAR (10 )
2967+ + ' EXEC '
2968+ + spi .proc_name
2969+ + ' '
2970+ + STUFF ((
2971+ SELECT DISTINCT ' , '
2972+ + spi2 .variable_name
2973+ + ' = '
2974+ + CASE WHEN spi2 .compile_time_value = ' NULL'
2975+ THEN spi2 .compile_time_value
2976+ ELSE QUOTENAME (spi2 .compile_time_value , ' '' ' )
2977+ END
2978+ FROM #stored_proc_info AS spi2
2979+ WHERE spi .QueryHash = spi2 .QueryHash
2980+ FOR XML PATH (N ' ' ), TYPE ).value (N ' .[1]' , N ' NVARCHAR(MAX)' ), 1 , 1 , N ' ' )
2981+ + CHAR (10 )
2982+ + ' -- ?>'
2983+ ) AS cached_execution_parameters
2984+ FROM #stored_proc_info AS spi
2985+ GROUP BY spi .SPID , spi .QueryHash , spi .proc_name
2986+ )
2987+ UPDATE b
2988+ SET b .implicit_conversion_info = CASE WHEN b .QueryType = ' Statement' THEN implicit_conversion_info_statement ELSE pk .implicit_conversion_info END ,
2989+ b .cached_execution_parameters = pk .cached_execution_parameters
2990+ FROM ##bou_BlitzCacheProcs AS b
2991+ JOIN precheck pk
2992+ ON pk .QueryHash = b .QueryHash
2993+ AND pk .SPID = b .SPID
2994+ AND b .implicit_conversions = 1
2995+ OPTION (RECOMPILE );
2996+
2997+ END -- End implicit conversion information gathering
2998+
2999+ UPDATE b
3000+ SET b .implicit_conversion_info = CASE WHEN b .implicit_conversion_info IS NULL THEN ' <?NoNeedToClickMe -- N/A --?>' ELSE b .implicit_conversion_info END ,
3001+ b .cached_execution_parameters = CASE WHEN b .cached_execution_parameters IS NULL THEN ' <?NoNeedToClickMe -- N/A --?>' ELSE b .cached_execution_parameters END
3002+ FROM ##bou_BlitzCacheProcs AS b
3003+ WHERE SPID = @@SPID
3004+ OPTION (RECOMPILE )
3005+
28293006IF @SkipAnalysis = 1
28303007 BEGIN
28313008 RAISERROR (N ' Skipping analysis, going to results' , 0 , 1 ) WITH NOWAIT ;
@@ -3396,6 +3573,8 @@ BEGIN
33963573 QueryText AS [Query Text],
33973574 QueryType AS [Query Type],
33983575 Warnings AS [Warnings],
3576+ implicit_conversion_info AS [Implicit Conversion Info],
3577+ cached_execution_parameters AS [Cached Execution Parameters],
33993578 ExecutionCount AS [# Executions],
34003579 ExecutionsPerMinute AS [Executions / Minute],
34013580 PercentExecutions AS [Execution Weight],
0 commit comments