SQL Scripting

A Progress Bar for SQL Scripts

Last year, I was running cursors against massive datasets, and they seemed to run forever. It was like watching paint dry or grass grow, because, while SQL Server Management Studio shows the time elapsed and a running ticker of (1 row(s) affected) messages, there is no indication of what percentage of the dataset has been processed. So I ended up developing this progress bar in SQL to add to my scripts.

The first step is to turn off the NOCOUNT option, which silences the default SSMS output.

SET NOCOUNT OFF;
GO

Next, we declare and initialize a few additional variables.

DECLARE @PROGRESS_MAX NUMERIC, @PROGRESS_CURRENT NUMERIC, @START DATETIME;
SELECT @START = GETDATE();
SELECT @PROGRESS_MAX = COUNT(*) FROM TempTable
SELECT @PROGRESS_CURRENT = COUNT(*) FROM TempTable WHERE Processed = 1

The variable @START allows the script to calculate the amount of time elapsed, @PROGRESS_MAX is the total number of records to be processed, and @PROGRESS_CURRENT is the total number of records that have already been processed. This methods permits you to restart the progress bar if the script terminates prematurely.

Just before the end of the cursor or loop, include the following script.

SET @PROGRESS_CURRENT = @PROGRESS_CURRENT + 1
IF @PROGRESS_CURRENT % 1000 = 0 PRINT CONCAT('Progress: ',@PROGRESS_CURRENT, REPLICATE(' ',8-LEN(@PROGRESS_CURRENT)),'[',REPLICATE('#',CEILING((@PROGRESS_CURRENT/@PROGRESS_MAX)*100)),'>',REPLICATE('.',99-CEILING((@PROGRESS_CURRENT/@PROGRESS_MAX)*100)),'] Time: ',CONVERT(varchar,DATEADD(ms,DATEDIFF(ms,@START,GETDATE()),0),114))
SQL Server Management Studio results pane showing the output from the SQL script.

This will increment the counter, and output the progress bar every thousand records.

The script uses CONCAT which was introduced in SQL Server 2012. If you are using an older version of SQL Server, then use the following instead:

SET @PROGRESS_CURRENT = @PROGRESS_CURRENT + 1
IF @PROGRESS_CURRENT % 1000 = 0 PRINT 'Progress: '+CONVERT(VARCHAR(10),@PROGRESS_CURRENT)+ REPLICATE(' ',8-LEN(@PROGRESS_CURRENT))+'['+REPLICATE('#',CEILING((@PROGRESS_CURRENT/@PROGRESS_MAX)*100))+'>'+REPLICATE('.',99-CEILING((@PROGRESS_CURRENT/@PROGRESS_MAX)*100))+'] Time: '+CONVERT(varchar,DATEADD(ms,DATEDIFF(ms,@START,GETDATE()),0),114)

This helps me maintain my sanity, and I hope it helps you as well.

Thanks for taking the time to read my post – I hope you found it helpful.
Leave feedback in the comments below.

If this post save you time, then consider sharing it with your friends and colleagues. If it saved you some money, then please consider buying me a coffee. If you want to know when I publish new content, then subscribe to my feed. Your support encourages me to write more. Thanks!

A Progress Bar for SQL Scripts

2 Comments

  1. Very new to SQL and running a long query written by a departed coworker. I’m getting this error:

    Msg 208, Level 16, State 1, Line 6
    Invalid object name ‘TempTable’.

    Do I need to manually create this table or define it somehwere? Thanks!

  2. This script was developed to be used inside a WHILE loop. I created a table ‘TempTable’ to manage the loop; the table contains the key for records to be processed, and a bit (1 = complete, 0 = pending). The loop is WHILE (SELECT * FROM TempTable WHERE Processed = 0). You can replace ‘TempTable’ with whatever you are using for your loop or cursor, but it’s an ideal application for temporary table.

Leave a Comment