Technical Articles

Monitoring SQL Server Progress in Visual Basic
Author:   Hans De Schrijver
Last Updated:   June 11, 2003
Technologies:   SQL Server 2000
Visual Basic 6.0

During the development of a calculation-intensive database project, developed in Visual Basic 6.0 and SQL Server 2000, the need arose to provide visual feedback to the user whenever lengthy database calculations were executing through a stored procedure. Something as simple as implementing a progress bar turned out to be somewhat of a challenge. This article presents the solution I implemented in the project. It was written for Visual Basic 6.0 and SQL Server 2000, using ADO 2.6. However, the code should work fine with earlier versions of Visual Basic and SQL Server.

The basis for the SQL Server progress implementation was originally described by Daniel Crane in an article titled "Return Long Progress From Long Running SP's". At the time of this writing, the article is available at http://www.planet-source-code.com/vb/scripts/ShowCode.asp?txtCodeId=683&lngWId=5


Project Scope

The problem we are solving in this article is rather common. Imagine you have a SQL Server stored procedure that either repeatedly executes a certain operation in a loop, exiting the loop when a certain condition is met, or sequentially executes a series of operations. When you execute that stored procedure - either in Query Analyzer or through an oConn.Execute statement in Visual Basic - the procedure does not return control until it is finished. For lenghty procedures this can be very cumbersome, especially in this day and age where users tend to be rather impatient. Providing some type of progress can greatly enhance the user's experience.
We will build a simple Visual Basic application that provides a highly accurate progress bar while monitoring the lengthy procedure's execution. The application will remain fully responsive during the procedure's execution.
The database portion of the project is written such that it supports an unlimited number of simultaneous executions, each with their own progress indication.
In order to create this project, I assume you are familiar with SQL Server, Query Analyzer and Visual Basic.

This article provides a step-by-step approach to building the project, explaining the code every step of the way.
Alternatively you can download the SQL scripts and Visual Basic code mentioned in this article, which are contained in a zip file:  MonitorSQLProgress.zip

(Step 1/6)
SQL Server - Creating the stored procedure

First let's create the stored procedure that will perform a lengthy operation. To mimic a lengthy operation, we make the stored procedure insert a given number of records into a temporary table.
Execute the following code in a Query Analyzer window.

/******************************************************************************
 * Name:        PR_LENGTHY_PROCEDURE 
 *
 * Description: Perform a lengthy operation by inserting a given number of
 *              records into a temporary table.
 *
 * Author:      Hans De Schrijver
 *
 * Input:       @Iterations (bigint)
 *              The number of records to insert into the temporary table.
 *              Default value is 10000.
 *
 * Output:      Returns a recordset with the content of the temporary table
 *              at the end of the procedure.
 *
 *****************************************************************************/
CREATE PROCEDURE PR_LENGTHY_PROCEDURE
(
    @Iterations bigint = 10000
)
AS

SET NOCOUNT ON

-- Drop the temporary table if it already exists 
-- (most likely a leftover from a previously cancelled procedure call).
IF OBJECT_ID('tempdb..#MyTempTable') IS NOT NULL
    DROP TABLE #MyTempTable

-- Create a temporary table in which we will insert a given number of records
-- in order to simulate a lenghty operation.
CREATE TABLE #MyTempTable(record_id bigint IDENTITY(1,1), record_description varchar(200))


-- Create and initialize the loop counter.
DECLARE @loopcounter bigint
SET @loopcounter = 0

-- Start the process of inserting records.
WHILE @loopcounter < @Iterations
BEGIN
    -- Insert a new record in the temporary table.
    SET @loopcounter = (@loopcounter + 1)
    INSERT #MyTempTable (record_description) VALUES ('This is Record #' + CONVERT(VARCHAR(20), @loopcounter))
END

-- Display the results from the temporary table.
SELECT * FROM #MyTempTable

-- Delete the temporary table.
DROP TABLE #MyTempTable

GO

Now open a new window in Query Analyzer and execute the procedure as follows:
EXEC PR_LENGTHY_PROCEDURE 20000
Notice that the procedure does not return the results until it is completed. This is the standard behavior of any procedure and demonstrates the problem.

Note: if the above statement executes within one or two seconds, you are working on a performant SQL Server and will need to use much higher numbers throughout the rest of this article in order to experience the effects.

© 2003 Punctual Graphics USA, Inc. All rights reserved.