From 14674469daec3df36f9850c3ba258f654db0646f Mon Sep 17 00:00:00 2001 From: Erik Darling <2136037+erikdarlingdata@users.noreply.github.com> Date: Tue, 3 Mar 2026 17:09:40 -0500 Subject: [PATCH] Fix query_snapshots_collector schema mismatch after sp_WhoIsActive upgrade MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit sp_WhoIsActive inserts into destination tables by ordinal position, not column name. When sp_WhoIsActive is updated and its output column order changes, existing daily tables (query_snapshots_YYYYMMDD) have the old column order, causing "Implicit conversion from data type xml to varchar" errors until the next day when a new table is created. Fix: wrap the insert in a nested TRY/CATCH. On error 257 (implicit conversion), drop and recreate the daily table from the current sp_WhoIsActive schema, then retry the insert. This makes upgrades work immediately without waiting for midnight table rotation. Tested on sql2017, sql2019, sql2025 — all had the error before, all pass clean after this fix. Co-Authored-By: Claude Opus 4.6 --- install/11_collect_query_snapshots.sql | 83 +++++++++++++++++++++++++- 1 file changed, 81 insertions(+), 2 deletions(-) diff --git a/install/11_collect_query_snapshots.sql b/install/11_collect_query_snapshots.sql index 4977d2c..e61046b 100644 --- a/install/11_collect_query_snapshots.sql +++ b/install/11_collect_query_snapshots.sql @@ -196,6 +196,10 @@ BEGIN /* Collect currently executing queries using sp_WhoIsActive + sp_WhoIsActive inserts by ordinal position, not column name. + If sp_WhoIsActive was updated and column order changed, + existing daily tables will have a schema mismatch. + Detect this and recreate the table if needed. */ SET @sql = N' EXECUTE ' + QUOTENAME(@whoisactive_database) + N'.dbo.sp_WhoIsActive @@ -208,8 +212,83 @@ BEGIN @get_memory_info = 1, @destination_table = ''' + @full_table_name + N''';'; - EXECUTE sys.sp_executesql - @sql; + BEGIN TRY + EXECUTE sys.sp_executesql + @sql; + END TRY + BEGIN CATCH + IF ERROR_NUMBER() = 257 /*Implicit conversion = column order mismatch*/ + BEGIN + IF @debug = 1 + BEGIN + RAISERROR(N'Schema mismatch detected on %s, recreating table', 0, 1, @full_table_name) WITH NOWAIT; + END; + + /*Drop the mismatched table*/ + SET @sql = + N'DROP TABLE ' + + @full_table_name + + N';'; + + EXECUTE sys.sp_executesql + @sql; + + /*Recreate from current sp_WhoIsActive schema*/ + SET @schema = N''; + + SET @sql = N' + EXECUTE ' + QUOTENAME(@whoisactive_database) + N'.dbo.sp_WhoIsActive + @get_transaction_info = 1, + @get_outer_command = 1, + @get_plans = 1, + @get_task_info = 2, + @get_additional_info = 1, + @find_block_leaders = 1, + @get_memory_info = 1, + @not_filter_type = ''database'', + @not_filter = ''PerformanceMonitor'', + @return_schema = 1, + @schema = @schema OUTPUT;'; + + EXECUTE sys.sp_executesql + @sql, + N'@schema nvarchar(max) OUTPUT', + @schema = @schema OUTPUT; + + SET @schema = + REPLACE + ( + @schema, + N'', + @full_table_name + ); + + EXECUTE sys.sp_executesql + @schema; + + /*Retry the insert*/ + SET @sql = N' + EXECUTE ' + QUOTENAME(@whoisactive_database) + N'.dbo.sp_WhoIsActive + @get_transaction_info = 1, + @get_outer_command = 1, + @get_plans = 1, + @get_task_info = 2, + @get_additional_info = 1, + @find_block_leaders = 1, + @get_memory_info = 1, + @destination_table = ''' + @full_table_name + N''';'; + + EXECUTE sys.sp_executesql + @sql; + + /*Recreate views for new schema*/ + EXECUTE collect.query_snapshots_create_views; + END; + ELSE + BEGIN + THROW; + END; + END CATCH; /* Get row count from last insertion