How to See Rowcounts and Execution Time for In-Flight Queries in SQL Server
I frequently need to see rowcounts and execution time for queries while they’re running. Maybe I’m troubleshooting a slow query …
Read Moreon • 3 min read
I use the SQL Agent a lot, and it is handy for a lot of things, but it can be frustrating to not be able to pass state information between steps.

For example, I have a job where I want to execute data verification steps against multiple tables. It makes sense to have the check for each table in its own step with a clear label to simplify troubleshooting– so when the job fails, you can see which step had an error and know from the name exactly what’s wrong. But I want all steps in the job to run, regardless of whether a step fails— I want to check for failure at the end.
The most basic way to do this is to have each job step log to a table. This isn’t really bad, but I’d rather not maintain a table for every job of this type. It leaves room for failure, it’s more to maintain, and it just feels redundant for the most part: all of the job history is tracked in MSDB anyway, shouldn’t I be able to use that?
The requirements I have for the job are:
So far this is working in my tests as the code for the final step, and it meets my needs for this type of job. Note: This uses a token to determine the job_id of the running job, so this will only work within the execution context of a SQL Agent job. If you want to test in a regular query, you’ll have to assign a fake job_id for your test. SQL Agent steps also don’t parse tokens successfully (at least in the version I’m using).
set quoted_identifier on;
declare @errorMsg nvarchar(max);
select
@errorMsg= 'The following steps failed, please investigate:' + LEFT(o.list, LEN(o.list)-1)
from (
select
[text()] = step_name + ','
FROM msdb.dbo.sysjobhistory jh
join msdb.dbo.sysjobactivity ja on
jh.job_id=ja.job_id
where
run_status=0 --step failed
and step_id != 0
and jh.job_id = CONVERT(uniqueidentifier, $(ESCAPE_NONE(JOBID)))
and --this block ensures that we just pull information from the most recent job run
(
-- The start time of the step, converted to datetime
CONVERT (DATETIME, RTRIM(run_date))
+ ( run_time * 9
+ run_time % 10000 * 6
+ run_time % 100 * 10
) / 216e4
>= ja.start_execution_date -- the time the job last started
)
order by instance_id
FOR XML PATH ('')
) o (list)
if @errorMsg is null
print ' Everything looks good...'
else
begin
raiserror (@errorMsg, 16, 1)
end
Copyright (c) 2025, Catalyze SQL, LLC; all rights reserved. Opinions expressed on this site are solely those of Kendra Little of Catalyze SQL, LLC. Content policy: Short excerpts of blog posts (3 sentences) may be republished, but longer excerpts and artwork cannot be shared without explicit permission.