I know that for many this won't be of value, because your systems are too busy for this to make sense and I also know that a new process could start while I'm running one of my statements, so this isn't fool-proof by any means.
-- ======================================================================== -- Author: Eric Zierdt -- Create date: 9/20/2016 -- Description: Checks database for running processes and Runs -- series of statements when free and emails when complete -- ======================================================================== /********************************************************************* ** CODE TO CREATE THE TABLE TO STORE THE QUERIES YOU WANT TO RUN ** *********************************************************************/ /* IF EXISTS (SELECT * FROM tempdb.dbo.sysobjects WHERE ID = OBJECT_ID(N'tempdb..##TABLE')) BEGIN DROP TABLE ##TABLE END CREATE TABLE ##TABLE (ID INT IDENTITY(1,1), Code VARCHAR(MAX),Complete BIT DEFAULT 0) INSERT INTO ##TABLE ( Code ) VALUES ('UPDATE STATISTICS [Table] [Stat] WITH FULLSCAN') */ SET NOCOUNT ON /***************************************************************************************** ** CREATING ##StartTime TABLE TO BE USED IN REMAINING TIME ESTIMATES IN OTHER QUERY. ** ** SETTING TO GLOBAL TEMP TABLE SO ACCESSABLE IN ANOTHER WINDOW ** *****************************************************************************************/ IF EXISTS (SELECT * FROM tempdb.dbo.sysobjects WHERE ID = OBJECT_ID(N'tempdb..##StartTime')) BEGIN DROP TABLE ##StartTime END CREATE TABLE ##StartTime (StartTime DATETIME) INSERT INTO ##StartTime VALUES ( GETDATE() ) PRINT 'Start Time: ' + CONVERT(VARCHAR(25), GETDATE(), 101) + ' ' + CONVERT(VARCHAR(25), GETDATE(), 108) GO /***************************************************************************************** ** CREATING ##StartTime TABLE TO BE USED IN REMAINING TIME ESTIMATES IN OTHER QUERY. ** ** SETTING TO GLOBAL TEMP TABLE SO ACCESSABLE IN ANOTHER WINDOW ** *****************************************************************************************/ DECLARE @ID INT ,@SQL VARCHAR(MAX) ,@StartTime DATETIME = GETDATE() ,@EndTime DATETIME WHILE ( SELECT COUNT(1) FROM ##TABLE WHERE Complete = 0 ) >= 1 BEGIN WHILE ( /************************************************************** ** CHECKING TO SEE IF DATABASE HAS NO 'RUNNABLE' PROCESSES ** **************************************************************/ SELECT COUNT(1) FROM sys.sysprocesses S WHERE status = 'runnable' AND DB_NAME(S.dbid) = DB_NAME() AND S.spid <> @@SPID ) > 0 BEGIN WAITFOR DELAY '00:00:05'; ---CHANGE TO MEET YOUR NEEDS; THIS IS SAYING, RETRY EVERY 5 SECONDS TO SEE IF DATABASE IS FREE TO DO WORK END /************************************************* ** NO 'RUNNING' PROCESSES DETECTED, RUN QUERY ** *************************************************/ SELECT TOP 1 @ID=ID, @SQL=Code FROM ##TABLE WHERE Complete = 0 EXEC(@SQL) UPDATE ##TABLE SET Complete = 1 WHERE ID = @ID END /********************************************* ** SET END TIME AND PRINT RUN TIME STATS ** *********************************************/ SET @EndTime = GETDATE() PRINT 'End Time: ' + CONVERT(VARCHAR(25), @EndTime, 101) + ' ' + CONVERT(VARCHAR(25), @EndTime, 108) PRINT 'Run Time: ' + CONVERT(VARCHAR, DATEADD(ms,DATEDIFF(ms,@StartTime,@EndTime),0),108) /************* ** CLEANUP ** *************/ DROP TABLE ##TABLE DROP TABLE ##StartTime /********************************************* ** SEND EMAIL NOTIFICATION OF COMPLETION ** *********************************************/ DECLARE @buffer_memory_used_MB FLOAT ,@Body VARCHAR(MAX) ,@Subject VARCHAR(255) = 'Auto Run Script Complete' ,@To VARCHAR(512) = 'In another window I will often run this on occasion to get some stats and an idea of how long it will run for:' SET @Body = ' The script has completed processing queries.
Run Time: ' + CONVERT(VARCHAR, DATEADD(ms,DATEDIFF(ms,@StartTime,@EndTime),0),108) + ' ' EXEC msdb.dbo.sp_send_dbmail @recipients = @To , @subject = @Subject , @body = @Body , @body_format = 'HTML'
DECLARE @Completed FLOAT ,@CompletedStatements FLOAT ,@Total FLOAT ,@TotalStatements FLOAT ,@PercentComplete FLOAT ,@StartDate DATETIME SELECT @StartDate=StartTime FROM ##StartTime DECLARE @RunTime BIGINT = DATEDIFF(SECOND,@StartDate,GETDATE()) SELECT @CompletedStatements = COUNT(1) FROM ##Table WHERE fixed = 1 SELECT @TotalStatements = COUNT(1) FROM ##Table SELECT @Completed = SUM([RowCount]) FROM ##Table WHERE fixed = 1 SELECT @Total = SUM([RowCount]) FROM ##Table SELECT @PercentComplete = 100*(@Completed/@Total) DECLARE @SecondPerRecord FLOAT = CAST(@RunTime AS FLOAT)/@Completed DECLARE @EstRemainingSeconds BIGINT = @SecondPerRecord*(@Total-@Completed) SELECT @Total TotalRecords, @Completed CompletedRecords, @TotalStatements as TotalStatements, @CompletedStatements as CompletedStatements, @PercentComplete [% Complete], @RunTime RunTimeSeconds, @SecondPerRecord SecondPerRecord, @EstRemainingSeconds EstRemainingSeconds ,@EstRemainingSeconds/60.0 EstRemainingMins, @EstRemainingSeconds/3600.0 EstRemainingHoursPlease comment below and let me know if you found value in this post.
Eric