Skip to content

Commit 11f50d4

Browse files
Fix query_snapshots_collector schema mismatch after sp_WhoIsActive upgrade (#401)
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 <noreply@anthropic.com>
1 parent 6e199c8 commit 11f50d4

1 file changed

Lines changed: 81 additions & 2 deletions

File tree

install/11_collect_query_snapshots.sql

Lines changed: 81 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,10 @@ BEGIN
196196

197197
/*
198198
Collect currently executing queries using sp_WhoIsActive
199+
sp_WhoIsActive inserts by ordinal position, not column name.
200+
If sp_WhoIsActive was updated and column order changed,
201+
existing daily tables will have a schema mismatch.
202+
Detect this and recreate the table if needed.
199203
*/
200204
SET @sql = N'
201205
EXECUTE ' + QUOTENAME(@whoisactive_database) + N'.dbo.sp_WhoIsActive
@@ -208,8 +212,83 @@ BEGIN
208212
@get_memory_info = 1,
209213
@destination_table = ''' + @full_table_name + N''';';
210214

211-
EXECUTE sys.sp_executesql
212-
@sql;
215+
BEGIN TRY
216+
EXECUTE sys.sp_executesql
217+
@sql;
218+
END TRY
219+
BEGIN CATCH
220+
IF ERROR_NUMBER() = 257 /*Implicit conversion = column order mismatch*/
221+
BEGIN
222+
IF @debug = 1
223+
BEGIN
224+
RAISERROR(N'Schema mismatch detected on %s, recreating table', 0, 1, @full_table_name) WITH NOWAIT;
225+
END;
226+
227+
/*Drop the mismatched table*/
228+
SET @sql =
229+
N'DROP TABLE ' +
230+
@full_table_name +
231+
N';';
232+
233+
EXECUTE sys.sp_executesql
234+
@sql;
235+
236+
/*Recreate from current sp_WhoIsActive schema*/
237+
SET @schema = N'';
238+
239+
SET @sql = N'
240+
EXECUTE ' + QUOTENAME(@whoisactive_database) + N'.dbo.sp_WhoIsActive
241+
@get_transaction_info = 1,
242+
@get_outer_command = 1,
243+
@get_plans = 1,
244+
@get_task_info = 2,
245+
@get_additional_info = 1,
246+
@find_block_leaders = 1,
247+
@get_memory_info = 1,
248+
@not_filter_type = ''database'',
249+
@not_filter = ''PerformanceMonitor'',
250+
@return_schema = 1,
251+
@schema = @schema OUTPUT;';
252+
253+
EXECUTE sys.sp_executesql
254+
@sql,
255+
N'@schema nvarchar(max) OUTPUT',
256+
@schema = @schema OUTPUT;
257+
258+
SET @schema =
259+
REPLACE
260+
(
261+
@schema,
262+
N'<table_name>',
263+
@full_table_name
264+
);
265+
266+
EXECUTE sys.sp_executesql
267+
@schema;
268+
269+
/*Retry the insert*/
270+
SET @sql = N'
271+
EXECUTE ' + QUOTENAME(@whoisactive_database) + N'.dbo.sp_WhoIsActive
272+
@get_transaction_info = 1,
273+
@get_outer_command = 1,
274+
@get_plans = 1,
275+
@get_task_info = 2,
276+
@get_additional_info = 1,
277+
@find_block_leaders = 1,
278+
@get_memory_info = 1,
279+
@destination_table = ''' + @full_table_name + N''';';
280+
281+
EXECUTE sys.sp_executesql
282+
@sql;
283+
284+
/*Recreate views for new schema*/
285+
EXECUTE collect.query_snapshots_create_views;
286+
END;
287+
ELSE
288+
BEGIN
289+
THROW;
290+
END;
291+
END CATCH;
213292

214293
/*
215294
Get row count from last insertion

0 commit comments

Comments
 (0)