Advertisement
uwekeim

ExpressMaint with "Continue on Error" option

Dec 27th, 2012
380
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
T-SQL 46.30 KB | None | 0 0
  1. /*
  2. Execute these commands e.g. inside Microsoft SQL Server Management Studio Express to create the ExpressMaint stored procedure to back up your databases.
  3.  
  4. Also see:
  5. - http://pastebin.com/znGVVkRj for the ExpressMaint prerequisites
  6. - http://expressmaint.codeplex.com for the ExpressMaint project
  7. */
  8.  
  9. USE [master]
  10. GO
  11.  
  12. SET ANSI_NULLS ON
  13. GO
  14. SET QUOTED_IDENTIFIER ON
  15. GO
  16.  
  17. ALTER PROCEDURE [dbo].[expressmaint]
  18. (
  19.    @database      sysname,                   -- database name | ALL_USER | ALL_SYSTEM
  20.    @optype        varchar(7),                -- LOG | DB | DIFF | REINDEX | REORG | CHECKDB
  21.    @backupwith    varchar(500) = NULL,       -- additional backup options
  22.    @backupfldr    varchar(200) = NULL,       -- folder to write backup to
  23.    @reportfldr    varchar(200) = NULL,       -- folder to write text report
  24.    @verify        bit = 1,                   -- verify backup
  25.    @verifywith    varchar(500) = NULL,       -- additional verify options
  26.    @dbretainunit  varchar(10)  = NULL,       -- minutes | hours | days | weeks | months | copies
  27.    @dbretainval   int = 1,                   -- specifies how many retainunits to keep backup
  28.    @report        bit = 1,                   -- flag to indicate whether to generate report
  29.    @rptretainunit varchar(10)  = NULL,       -- minutes | hours | days | weeks | months | copies
  30.    @rptretainval  int = 1,                   -- specifies how many retainunits to keep reports
  31.    @checkattrib   bit = 0,                   -- check if archive bit is cleared before deleting
  32.    @delfirst      bit = 0,                   -- delete before backup (handy if space issues)
  33.    @debug         bit = 0,                   -- print commands to be executed
  34.    @compression   bit = 0,                    -- backup compression (SQL 2008 Enterprise Edition only)
  35.    @continue_on_error bit = 1           -- whether to continue on error. UWE KEIM 2012-12-27.
  36. )
  37. AS
  38. /*
  39.    ExpressMaintTSQL
  40.    
  41.    see http://www.sqldbatips.com/showarticle.asp?ID=27 for documentation
  42.    
  43.    Date           Author                  Notes
  44.    24/07/2004     Jasper Smith            Initial release
  45.    28/07/2008     Jasper Smith            Fixed datepart issue with MONTHS retention unit
  46.    06/12/2008     Jasper Smith            Added SQL 2008 support plus some minor fixes
  47.    12/27/2012     Uwe Keim                Added option to continue on error
  48.  
  49. */
  50. SET NOCOUNT ON
  51. SET ARITHABORT ON
  52. SET DATEFORMAT YMD
  53.  
  54. /************************
  55.    VARIABLE DECLARATION
  56. ************************/
  57.  
  58.    DECLARE @fso             int
  59.    DECLARE @file            int
  60.    DECLARE @reportfilename  varchar(500)
  61.    DECLARE @backupfilename  varchar(500)
  62.    DECLARE @delfilename     varchar(500)
  63.    DECLARE @cmd             varchar(650)
  64.    DECLARE @backupfldrorig  varchar(200)
  65.    DECLARE @databaseorig    sysname
  66.    DECLARE @table           nvarchar(600)
  67.    DECLARE @exists          varchar(5)
  68.    DECLARE @err             int
  69.    DECLARE @start           datetime
  70.    DECLARE @finish          datetime
  71.    DECLARE @runtime         datetime
  72.    DECLARE @output          varchar(200)
  73.    DECLARE @errormsg        varchar(210)
  74.    DECLARE @datepart        nchar(2)
  75.    DECLARE @execmd          nvarchar(1000)
  76.    DECLARE @delcmd          nvarchar(1000)
  77.    DECLARE @exemsg          varchar(8000)
  78.    DECLARE @filecount       int              ; SET @filecount    = 0
  79.    DECLARE @delcount        int              ; SET @delcount     = 0
  80.    DECLARE @hr              int              ; SET @hr           = 0
  81.    DECLARE @ret             int              ; SET @ret          = 0
  82.    DECLARE @cmdret          int              ; SET @cmdret       = 0
  83.    DECLARE @delbkflag       int              ; SET @delbkflag    = 0
  84.    DECLARE @delrptflag      int              ; SET @delrptflag   = 0
  85.    DECLARE @filecrt         int              ; SET @filecrt      = 0
  86.    DECLARE @user            sysname          ; SET @user         = SUSER_SNAME()
  87.    DECLARE @jobdt           datetime         ; SET @jobdt        = GETDATE()
  88.    DECLARE @jobstart        char(12)         ;
  89.    DECLARE @stage           int              ; SET @stage        = 1
  90.    DECLARE @compressok      bit              ; SET @compressok   = 0
  91.    DECLARE @versionmajor    int              
  92.    DECLARE @engineedition   int
  93.  
  94.    SET @jobstart = CONVERT(char(8),@jobdt,112)+LEFT(REPLACE(CONVERT(char(8),@jobdt,108),':',''),4)  
  95.    IF RIGHT(@reportfldr,1)<>'\' SET @reportfldr = @reportfldr + '\'
  96.    IF RIGHT(@backupfldr,1)<>'\' SET @backupfldr = @backupfldr + '\'
  97.    SET @backupfldrorig = @backupfldr
  98.    SET @databaseorig = @database
  99.  
  100.    SELECT @versionmajor = CAST(LEFT(CAST(SERVERPROPERTY('ProductVersion') as varchar(128)),CHARINDEX('.',CAST(SERVERPROPERTY('ProductVersion') as varchar(128)))-1) as int),
  101.           @engineedition = CAST(SERVERPROPERTY('EngineEdition') as int)
  102.    IF (@versionmajor>=10 AND @engineedition = 3) SET @compressok = 1
  103.  
  104.    CREATE TABLE #files(filename varchar(255))  
  105.    CREATE TABLE #exists(exist int,isdir int,parent int)
  106.    CREATE TABLE #databases(dbname sysname)
  107.  
  108. /**********************************
  109.      INITIALIZE FSO IF @report = 1
  110. ***********************************/
  111.  
  112.    IF @report = 1
  113.    BEGIN
  114.       EXEC @hr=sp_OACreate 'Scripting.FileSystemObject',@fso OUT
  115.       IF @hr <> 0
  116.       BEGIN  
  117.          EXEC sp_OAGetErrorInfo @fso
  118.          RAISERROR('Error creating File System Object',16,1)
  119.          SET @ret = 1
  120.         GOTO CLEANUP   
  121.       END
  122.    END
  123.  
  124. /************************
  125.        CHECK INPUT
  126. ************************/
  127.  
  128.    -- check SQL2005 or higher
  129.    IF @versionmajor<9
  130.     BEGIN                                  
  131.     RAISERROR('SQL2005 or higher is required for sp_expressmaint',16,1)
  132.       SET @ret = 1
  133.     GOTO CLEANUP   
  134.     END
  135.    
  136.    -- check sysadmin
  137.    IF IS_SRVROLEMEMBER('sysadmin') = 0
  138.     BEGIN                                  
  139.     RAISERROR('The current user %s is not a member of the sysadmin role',16,1,@user)
  140.       SET @ret = 1
  141.     GOTO CLEANUP   
  142.     END
  143.  
  144.    -- check database exists and is online
  145.    IF @database NOT IN ('ALL_USER','ALL_SYSTEM')
  146.    BEGIN
  147.       IF (DB_ID(@database) IS NULL) OR ((select state from sys.databases where name = @database) <>0)
  148.     BEGIN                                  
  149.         RAISERROR('Database %s is invalid or database status is not ONLINE',16,1,@database)
  150.          SET @ret = 1
  151.         GOTO CLEANUP       
  152.     END
  153.    END
  154.  
  155.    -- check @optype is valid
  156.    IF UPPER(@optype) NOT IN ('LOG','DB','DIFF','REINDEX','REORG','CHECKDB')
  157.     BEGIN                                  
  158.     RAISERROR('%s is not a valid option for @optype',16,1,@optype)
  159.       SET @ret = 1
  160.     GOTO CLEANUP       
  161.     END
  162.  
  163.    -- check recovery mode is correct if trying log backup
  164.    IF @database NOT IN ('ALL_USER','ALL_SYSTEM')
  165.    BEGIN
  166.       IF (@optype = 'LOG' and ((select recovery_model from sys.databases where name = @database) = 3))
  167.     BEGIN                                  
  168.         RAISERROR('%s is not a valid option for database %s because it is in SIMPLE recovery mode',16,1,@optype,@database)
  169.          SET @ret = 1
  170.         GOTO CLEANUP   
  171.     END
  172.    END
  173.  
  174.    -- no log backups for system databases
  175.    IF @database = 'ALL_SYSTEM'
  176.    BEGIN
  177.       IF @optype = 'LOG'
  178.     BEGIN                                  
  179.         RAISERROR('%s is not a valid option for the option ALL_SYSTEM',16,1,@optype)
  180.          SET @ret = 1
  181.         GOTO CLEANUP   
  182.     END
  183.    END
  184.  
  185.    -- check that @backupfldr exists on the server
  186.    IF @optype NOT IN ('REINDEX','CHECKDB','REORG')
  187.    BEGIN
  188.       IF @report = 1
  189.       BEGIN
  190.          EXEC sp_OAMethod @fso,'FolderExists',@exists OUT,@backupfldr
  191.          IF @exists <> 'True'
  192.         BEGIN                                  
  193.             RAISERROR('The folder %s does not exist on this server',16,1,@backupfldr)
  194.             SET @ret = 1
  195.             GOTO CLEANUP   
  196.         END
  197.       END
  198.       ELSE
  199.       BEGIN
  200.          INSERT #exists
  201.          EXEC master.dbo.xp_fileexist @backupfldr
  202.          IF (SELECT MAX(isdir) FROM #exists)<>1
  203.         BEGIN                                  
  204.             RAISERROR('The folder %s does not exist on this server',16,1,@backupfldr)
  205.             SET @ret = 1
  206.             GOTO CLEANUP   
  207.         END
  208.       END
  209.    END
  210.  
  211.    -- check that @reportfldr exists on the server
  212.    IF @reportfldr IS NOT NULL or @report = 1
  213.    BEGIN
  214.       IF @report = 1
  215.       BEGIN
  216.          EXEC sp_OAMethod @fso,'FolderExists',@exists OUT,@reportfldr
  217.          IF @exists <> 'True'
  218.         BEGIN                                  
  219.             RAISERROR('The folder %s does not exist on this server',16,1,@reportfldr)
  220.             SET @ret = 1
  221.             GOTO CLEANUP   
  222.         END
  223.       END
  224.       ELSE
  225.       BEGIN
  226.          DELETE #exists
  227.          INSERT #exists
  228.          EXEC master.dbo.xp_fileexist @reportfldr
  229.          IF (SELECT MAX(isdir) FROM #exists)<>1
  230.         BEGIN                                  
  231.             RAISERROR('The folder %s does not exist on this server',16,1,@reportfldr)
  232.             SET @ret = 1
  233.             GOTO CLEANUP   
  234.         END
  235.       END
  236.    END
  237.  
  238.    -- check @dbretainunit is a vaild value
  239.    IF @optype NOT IN ('REINDEX','CHECKDB','REORG')
  240.    BEGIN
  241.       IF UPPER(@dbretainunit) NOT IN ('MINUTES','HOURS','DAYS','WEEKS','MONTHS','COPIES')
  242.         BEGIN                                  
  243.         RAISERROR('%s is not a valid value for @dbretainunit (''minutes | hours | days | weeks | months | copies'')',16,1,@dbretainunit)
  244.          SET @ret = 1
  245.         GOTO CLEANUP   
  246.     END
  247.    END
  248.  
  249.    --check @dbretainval is a vaild value
  250.    IF @dbretainval<1
  251.     BEGIN                                  
  252.     RAISERROR('%i is not a valid value for @dbretainval (must be >0)',16,1,@dbretainval)
  253.       SET @ret = 1
  254.     GOTO CLEANUP   
  255.     END
  256.  
  257.    -- check @rptretainunit is a vaild value if present
  258.    IF UPPER(@rptretainunit) NOT IN ('MINUTES','HOURS','DAYS','WEEKS','MONTHS','COPIES') and @rptretainunit IS NOT NULL
  259.     BEGIN                                  
  260.     RAISERROR('%s is not a valid value for @rptretainunit (''minutes | hours | days | weeks | months | copies'')',16,1,@rptretainunit)
  261.       SET @ret = 1
  262.     GOTO CLEANUP   
  263.     END
  264.  
  265.    --check @rptretainval is a vaild value
  266.    IF @rptretainval<1
  267.     BEGIN                                  
  268.     RAISERROR('%i is not a valid value for @rptretainval (must be >0)',16,1,@rptretainval)
  269.       SET @ret = 1
  270.     GOTO CLEANUP   
  271.     END
  272.  
  273.  
  274. /***********************************
  275.    list of databases to process
  276. ************************************/
  277.  
  278.    IF @database IN ('ALL_USER','ALL_SYSTEM')
  279.    BEGIN
  280.       IF @database = 'ALL_USER'
  281.          INSERT #databases(dbname)
  282.          SELECT [name] from sys.databases where database_id > 4
  283.          AND (@optype <> 'LOG' OR recovery_model <> '3')
  284.       ELSE
  285.          INSERT #databases(dbname)
  286.          SELECT [name] from sys.databases where database_id in (1,3,4)
  287.    END
  288.    ELSE
  289.       INSERT #databases(dbname) SELECT @database
  290.  
  291.  
  292. /***********************************
  293.    INITIALIZE REPORT IF @report = 1
  294. ************************************/
  295.  
  296.    -- generate report filename
  297.    SELECT @reportfilename = @reportfldr + REPLACE(REPLACE(@database,' ','_'),'''','_') +
  298.    CASE WHEN UPPER(@optype) = 'DB'   THEN '_FullDBBackup_report_'
  299.         WHEN UPPER(@optype) = 'DIFF' THEN '_DiffDBBackup_report_'
  300.         WHEN UPPER(@optype) = 'LOG'  THEN '_LogBackup_report_'  
  301.         WHEN UPPER(@optype) = 'REINDEX'  THEN '_Reindex_report_'    
  302.         WHEN UPPER(@optype) = 'REORG'  THEN '_Reorg_report_'  
  303.         WHEN UPPER(@optype) = 'CHECKDB'  THEN '_CheckDB_report_'      
  304.    END + @jobstart + '.txt'
  305.  
  306.    -- if no report just set @reportfilename to NULL
  307.    IF @report = 0 SET @reportfilename = NULL
  308.  
  309.    IF @debug = 1
  310.    BEGIN
  311.       PRINT '@reportfilename = ' + ISNULL(@reportfilename,'NULL')
  312.    END
  313.  
  314.    IF @report = 1
  315.    BEGIN
  316.       -- create report file
  317.       EXEC @hr=sp_OAMethod @fso, 'CreateTextFile',@file OUT, @reportfilename
  318.       IF (@hr <> 0)
  319.       BEGIN
  320.          EXEC sp_OAGetErrorInfo @fso
  321.          RAISERROR('Error creating log file',16,1)
  322.          SET @ret = 1
  323.         GOTO CLEANUP   
  324.       END
  325.       ELSE
  326.          -- set global flag to indicate we have created a report file
  327.          SET @filecrt = 1
  328.  
  329.       -- write header  
  330.       EXEC sp_OAMethod @file,'WriteLine',NULL,''
  331.       SET @output = 'Expressmaint utility, Logged on to SQL Server [' + @@SERVERNAME + '] as ' + '[' + @user + ']'
  332.       IF @debug = 1 PRINT @output
  333.       EXEC sp_OAMethod @file,'WriteLine',NULL,@output      
  334.      
  335.  
  336.       IF UPPER(@optype) NOT IN ('REINDEX','CHECKDB','REORG')
  337.       BEGIN
  338.          SET @output = 'Starting backup on ' + convert(varchar(25),getdate(),100)
  339.       END
  340.       IF UPPER(@optype) = 'CHECKDB'
  341.       BEGIN
  342.          SET @output = 'Starting CheckDB on ' + convert(varchar(25),getdate(),100)
  343.       END      
  344.       IF UPPER(@optype) IN ('REINDEX','REORG')
  345.       BEGIN
  346.          SET @output = 'Starting Reindex on ' + convert(varchar(25),getdate(),100)
  347.       END
  348.  
  349.       IF @debug = 1 PRINT @output
  350.       EXEC sp_OAMethod @file,'WriteLine',NULL,@output
  351.       EXEC sp_OAMethod @file,'WriteLine',NULL,''
  352.    END
  353.  
  354. /************************
  355.      BACKUP ACTIONS
  356. ************************/
  357.  
  358.    IF  UPPER(@optype) = 'CHECKDB' GOTO CHECK_DB
  359.    IF  UPPER(@optype) IN ('REINDEX','REORG') GOTO REINDEX
  360.    
  361.    -- if @delfirst = 1  we need to delete prior backups that qualify
  362.    IF @delfirst = 1 GOTO DELFIRST
  363.  
  364.    -- this label is so that we can return here after deleting files if @delfirst = 1
  365.    DOBACKUP:
  366.  
  367.    DECLARE dcur CURSOR LOCAL FAST_FORWARD
  368.    FOR SELECT dbname FROM #databases ORDER BY dbname
  369.    OPEN dcur
  370.    FETCH NEXT FROM dcur into @database
  371.    WHILE @@FETCH_STATUS=0
  372.    BEGIN
  373.    
  374.       -- set backup start time
  375.       SET @start = GETDATE()
  376.    
  377.       -- write to text report
  378.       IF @report = 1
  379.       BEGIN
  380.          SET @output = '[' + CAST(@stage as varchar(10)) + '] Database ' + @database + ': ' +
  381.                        CASE WHEN UPPER(@optype) = 'DB'   THEN 'Full Backup '
  382.                             WHEN UPPER(@optype) = 'DIFF' THEN 'Differential Backup '
  383.                             WHEN UPPER(@optype) = 'LOG'  THEN 'Log Backup '        
  384.                        END + 'starting at ' + CONVERT(varchar(25),@start,100)
  385.          IF @debug = 1 PRINT @output
  386.          EXEC sp_OAMethod @file,'WriteLine',NULL,@output
  387.       END
  388.  
  389.       -- backup subfolder
  390.       SET @execmd = 'IF NOT EXIST "' + @backupfldrorig + REPLACE(@database,'''','') + '\" MKDIR "' + @backupfldrorig + REPLACE(@database,'''','') + '\"'
  391.       EXEC master.dbo.xp_cmdshell @execmd,no_output
  392.       SET @backupfldr = @backupfldrorig + REPLACE(@database,'''','') + '\'
  393.  
  394.       SELECT @backupfilename = @backupfldr + REPLACE(REPLACE(@database,' ','_'),'''','_') +
  395.       CASE WHEN UPPER(@optype) = 'DB'   THEN '_FullDBBackup_'
  396.            WHEN UPPER(@optype) = 'DIFF' THEN '_DiffDBBackup_'
  397.            WHEN UPPER(@optype) = 'LOG'  THEN '_LogBackup_'        
  398.       END + @jobstart +
  399.       CASE WHEN UPPER(@optype) = 'LOG' THEN '.TRN' ELSE '.BAK' END
  400.          
  401.       /************************
  402.              FULL BACKUP
  403.       ************************/
  404.    
  405.       IF UPPER(@optype) = 'DB'
  406.       BEGIN
  407.    
  408.          IF @compression=1 AND @compressok=1
  409.             SET @execmd = N'BACKUP DATABASE [' + @database + '] TO DISK = ''' + @backupfilename + '''' +
  410.                            ' WITH COMPRESSION' + CASE WHEN @backupwith IS NULL THEN '' ELSE (',' + @backupwith) END
  411.          ELSE
  412.             SET @execmd = N'BACKUP DATABASE [' + @database + '] TO DISK = ''' + @backupfilename + '''' +
  413.                           CASE WHEN @backupwith IS NULL THEN '' ELSE (' WITH ' + @backupwith) END
  414.    
  415.          IF @debug = 1 PRINT 'FULL BACKUP : ' + @execmd
  416.  
  417.          BEGIN TRY
  418.    
  419.             EXEC(@execmd)
  420.    
  421.          END TRY
  422.          BEGIN CATCH -- backup failure
  423.             SELECT @err = @@ERROR,@ret = @err
  424.             SELECT @errormsg = 'Full backup of database ' + @database + ' failed with error : ' +  CAST(@err as varchar(10))
  425.             SET @output = SPACE(4) + '*** ' + @errormsg + ' ***'
  426.             IF @debug = 1 PRINT @output
  427.             IF @report = 1
  428.             BEGIN
  429.                EXEC sp_OAMethod @file,'WriteLine',NULL,@output
  430.                SET @output = SPACE(4) + 'Refer to SQL Error Log and NT Event Log for further details'
  431.                EXEC sp_OAMethod @file,'WriteLine',NULL,@output
  432.                EXEC sp_OAMethod @file,'WriteLine',NULL,''
  433.             END
  434.  
  435.         IF @continue_on_error <> 1
  436.         BEGIN
  437.             CLOSE dcur
  438.             DEALLOCATE dcur
  439.             GOTO CLEANUP
  440.         END  
  441.          END CATCH
  442.          
  443.          -- backup success
  444.          SET @finish = GETDATE()
  445.          SET @output = SPACE(4) + 'Database backed up to ' + @backupfilename
  446.          IF @debug = 1 PRINT @output
  447.          IF @report = 1
  448.          BEGIN
  449.             EXEC sp_OAMethod @file,'WriteLine',NULL,@output
  450.          END
  451.    
  452.          --calculate backup runtime
  453.          SET @runtime = (@finish - @start)
  454.          SET @output = SPACE(4) + 'Full database backup completed in '
  455.                      + CAST(DATEPART(hh,@runtime) as varchar(2)) + ' hour(s) '
  456.                      + CAST(DATEPART(mi,@runtime) as varchar(2)) + ' min(s) '
  457.                      + CAST(DATEPART(ss,@runtime) as varchar(2)) + ' second(s)'
  458.          IF @debug = 1 PRINT @output
  459.          IF @report = 1
  460.          BEGIN
  461.             EXEC sp_OAMethod @file,'WriteLine',NULL,@output
  462.             EXEC sp_OAMethod @file,'WriteLine',NULL,''
  463.          END
  464.    
  465.       END
  466.    
  467.    
  468.       /************************
  469.          DIFFERENTIAL BACKUP
  470.       ************************/
  471.    
  472.       IF UPPER(@optype) = 'DIFF'
  473.       BEGIN
  474.  
  475.          IF @compression=1 AND @compressok=1
  476.             SET @execmd = N'BACKUP DATABASE [' + @database + '] TO DISK = ''' + @backupfilename + '''' +
  477.                           N' WITH DIFFERENTIAL,COMPRESSION' + CASE WHEN @backupwith IS NULL THEN N'' ELSE (N',' + @backupwith) END
  478.          ELSE
  479.             SET @execmd = N'BACKUP DATABASE [' + @database + '] TO DISK = ''' + @backupfilename + N''' WITH DIFFERENTIAL' +
  480.                           CASE WHEN @backupwith IS NULL THEN N'' ELSE (N',' + @backupwith) END
  481.  
  482.          IF @debug = 1 PRINT 'DIFFERENTIAL BACKUP : ' + @execmd
  483.  
  484.          BEGIN TRY
  485.    
  486.             EXEC(@execmd)
  487.    
  488.          END TRY
  489.          BEGIN CATCH -- backup failure
  490.    
  491.             SELECT @err = @@ERROR,@ret = @err
  492.             SELECT @errormsg = 'Differential backup of database ' + @database + ' failed with error : ' +  CAST(@err as varchar(10))
  493.             SET @output = SPACE(4) + '*** ' + @errormsg + ' ***'
  494.             IF @debug = 1 PRINT @output
  495.             IF @report = 1
  496.             BEGIN
  497.                EXEC sp_OAMethod @file,'WriteLine',NULL,@output
  498.                SET @output = SPACE(4) + 'Refer to SQL Error Log and NT Event Log for further details'
  499.                EXEC sp_OAMethod @file,'WriteLine',NULL,@output
  500.             END
  501.  
  502.         IF @continue_on_error <> 1
  503.         BEGIN
  504.             CLOSE dcur
  505.             DEALLOCATE dcur
  506.             GOTO CLEANUP
  507.         END  
  508.    
  509.          END CATCH
  510.          
  511.          -- backup success
  512.          SET @finish = GETDATE()
  513.          SET @output = SPACE(4) + 'Database backed up to ' + @backupfilename
  514.          IF @debug = 1 PRINT @output
  515.          IF @report = 1
  516.          BEGIN
  517.             EXEC sp_OAMethod @file,'WriteLine',NULL,@output
  518.          END
  519.    
  520.          --calculate backup runtime
  521.          SET @runtime = (@finish - @start)
  522.          SET @output = SPACE(4) + 'Differential database backup completed in '
  523.                      + CAST(DATEPART(hh,@runtime) as varchar(2)) + ' hour(s) '
  524.                      + CAST(DATEPART(mi,@runtime) as varchar(2)) + ' min(s) '
  525.                      + CAST(DATEPART(ss,@runtime) as varchar(2)) + ' second(s)'
  526.          IF @debug = 1 PRINT @output
  527.          IF @report = 1
  528.          BEGIN
  529.             EXEC sp_OAMethod @file,'WriteLine',NULL,@output
  530.             EXEC sp_OAMethod @file,'WriteLine',NULL,''
  531.          END
  532.    
  533.       END
  534.    
  535.       /************************
  536.              LOG BACKUP
  537.       ************************/
  538.      
  539.       IF UPPER(@optype) = 'LOG'
  540.       BEGIN
  541.  
  542.          IF @compression=1 AND @compressok=1
  543.             SET @execmd = N'BACKUP LOG [' + @database + '] TO DISK = ''' + @backupfilename + '''' +
  544.                            ' WITH COMPRESSION' + CASE WHEN @backupwith IS NULL THEN '' ELSE (',' + @backupwith) END
  545.          ELSE
  546.             SET @execmd = N'BACKUP LOG [' + @database + '] TO DISK = ''' + @backupfilename + '''' +
  547.                           CASE WHEN @backupwith IS NULL THEN '' ELSE (' WITH ' + @backupwith) END
  548.      
  549.          IF @debug = 1 PRINT 'LOG BACKUP : ' + @execmd
  550.    
  551.          BEGIN TRY
  552.    
  553.             EXEC(@execmd)
  554.    
  555.          END TRY
  556.          BEGIN CATCH -- backup failure
  557.    
  558.             SELECT @err = @@ERROR,@ret = @err
  559.             SELECT @errormsg = 'Log backup of database ' + @database + ' failed with error : ' +  CAST(@err as varchar(10))        
  560.             SET @output = SPACE(4) + '*** ' + @errormsg + ' ***'
  561.             IF @debug = 1 PRINT @output
  562.             IF @report = 1
  563.             BEGIN
  564.                EXEC sp_OAMethod @file,'WriteLine',NULL,@output
  565.                SET @output = SPACE(4) + 'Refer to SQL Error Log and NT Event Log for further details'
  566.                EXEC sp_OAMethod @file,'WriteLine',NULL,@output
  567.             END
  568.  
  569.         IF @continue_on_error <> 1
  570.         BEGIN
  571.             CLOSE dcur
  572.             DEALLOCATE dcur
  573.             GOTO CLEANUP
  574.         END  
  575.    
  576.          END CATCH
  577.          
  578.          -- backup success
  579.          SET @finish = GETDATE()
  580.          SET @output = SPACE(4) + 'Log backed up to ' + @backupfilename
  581.          IF @debug = 1 PRINT @output
  582.          IF @report = 1
  583.          BEGIN
  584.             EXEC sp_OAMethod @file,'WriteLine',NULL,@output
  585.          END
  586.    
  587.          --calculate backup runtime
  588.          SET @runtime = (@finish - @start)
  589.          SET @output = SPACE(4) + 'Log backup completed in '
  590.                      + CAST(DATEPART(hh,@runtime) as varchar(2)) + ' hour(s) '
  591.                      + CAST(DATEPART(mi,@runtime) as varchar(2)) + ' min(s) '
  592.                      + CAST(DATEPART(ss,@runtime) as varchar(2)) + ' second(s)'
  593.          IF @debug = 1 PRINT @output
  594.          IF @report = 1
  595.          BEGIN
  596.             EXEC sp_OAMethod @file,'WriteLine',NULL,@output
  597.             EXEC sp_OAMethod @file,'WriteLine',NULL,''
  598.          END
  599.    
  600.       END
  601.  
  602.       SET @stage = (@stage + 1)
  603.  
  604.       FETCH NEXT FROM dcur into @database
  605.    END
  606.  
  607.    CLOSE dcur
  608.    DEALLOCATE dcur
  609.      
  610.    /************************
  611.          VERIFY BACKUP
  612.    ************************/
  613.  
  614.    IF @verify = 1
  615.    BEGIN
  616.  
  617.       DECLARE dcur CURSOR LOCAL FAST_FORWARD
  618.       FOR SELECT dbname FROM #databases ORDER BY dbname
  619.       OPEN dcur
  620.       FETCH NEXT FROM dcur into @database
  621.       WHILE @@FETCH_STATUS=0
  622.       BEGIN
  623.    
  624.          SELECT @backupfilename = @backupfldrorig + REPLACE(@database,'''','') + '\' + REPLACE(REPLACE(@database,' ','_'),'''','_') +
  625.          CASE WHEN UPPER(@optype) = 'DB'   THEN '_FullDBBackup_'
  626.               WHEN UPPER(@optype) = 'DIFF' THEN '_DiffDBBackup_'
  627.               WHEN UPPER(@optype) = 'LOG'  THEN '_LogBackup_'        
  628.          END + @jobstart +
  629.          CASE WHEN UPPER(@optype) = 'LOG' THEN '.TRN' ELSE '.BAK' END
  630.      
  631.          SET @start = GETDATE()
  632.    
  633.          -- write to text report
  634.          IF @report = 1
  635.          BEGIN
  636.             EXEC sp_OAMethod @file,'WriteLine',NULL,''
  637.             SET @output = '[' + CAST(@stage as varchar(10)) + '] Database ' + @database + ': Verify Backup File...'
  638.             IF @debug = 1 PRINT @output
  639.             EXEC sp_OAMethod @file,'WriteLine',NULL,@output  
  640.          END
  641.          
  642.          SET @execmd = N'RESTORE VERIFYONLY FROM DISK = ''' + @backupfilename + '''' +
  643.                        CASE WHEN @verifywith IS NULL THEN '' ELSE (' WITH ' + @verifywith) END
  644.          
  645.          BEGIN TRY
  646.    
  647.             EXEC(@execmd)
  648.    
  649.          END TRY
  650.          BEGIN CATCH
  651.    
  652.             SELECT @err = @@ERROR,@ret = @err
  653.             SET @errormsg = 'Verify of ' + @backupfilename + ' failed with Native Error : ' + CAST(@err as varchar(10))
  654.             SET @output = SPACE(4) + '*** ' + @errormsg + ' ***'
  655.             IF @debug = 1 PRINT @output
  656.             IF @report = 1
  657.             BEGIN
  658.                EXEC sp_OAMethod @file,'WriteLine',NULL,@output
  659.             END
  660.  
  661.         IF @continue_on_error <> 1
  662.         BEGIN
  663.             CLOSE dcur
  664.             DEALLOCATE dcur
  665.             GOTO CLEANUP
  666.         END  
  667.    
  668.          END CATCH
  669.    
  670.          -- verify success
  671.          SET @finish = GETDATE()
  672.          SET @output = SPACE(4) + 'Backup file ' + @backupfilename + ' verified'
  673.          IF @debug = 1 PRINT @output
  674.    
  675.          IF @report = 1
  676.          BEGIN
  677.             EXEC sp_OAMethod @file,'WriteLine',NULL,@output
  678.          END
  679.    
  680.          --calculate verify runtime
  681.          SET @runtime = (@finish - @start)
  682.          SET @output = SPACE(4) + 'Verify backup completed in '
  683.                      + CAST(DATEPART(hh,@runtime) as varchar(2)) + ' hour(s) '
  684.                      + CAST(DATEPART(mi,@runtime) as varchar(2)) + ' min(s) '
  685.                      + CAST(DATEPART(ss,@runtime) as varchar(2)) + ' second(s)'
  686.          IF @debug = 1 PRINT @output
  687.          IF @report = 1
  688.          BEGIN
  689.             EXEC sp_OAMethod @file,'WriteLine',NULL,@output
  690.          END
  691.  
  692.          SET @stage = (@stage + 1)
  693.          FETCH NEXT FROM dcur into @database
  694.       END    
  695.  
  696.       CLOSE dcur
  697.       DEALLOCATE dcur
  698.    END
  699.  
  700. /************************
  701.     DELETE OLD FILES
  702. ************************/
  703.  
  704.  
  705.    -- we have already deleted files so skip to the end
  706.    IF @delfirst = 1 GOTO CLEANUP
  707.  
  708.    -- this label is so that we can delete files prior to backup if @delfirst = 1
  709.    DELFIRST:
  710.  
  711.    /************************
  712.       DELETE OLD BACKUPS
  713.    ************************/
  714.  
  715.    SET @datepart = CASE
  716.       WHEN UPPER(@dbretainunit) = 'MINUTES' THEN N'mi'
  717.       WHEN UPPER(@dbretainunit) = 'HOURS'   THEN N'hh'
  718.       WHEN UPPER(@dbretainunit) = 'DAYS'    THEN N'dd'
  719.       WHEN UPPER(@dbretainunit) = 'WEEKS'   THEN N'ww'
  720.       WHEN UPPER(@dbretainunit) = 'MONTHS'  THEN N'mm'
  721.    END
  722.  
  723.    IF @debug = 1 PRINT '@datepart for backups = ' + @datepart
  724.  
  725.    -- write to text report
  726.    IF @report = 1
  727.    BEGIN
  728.       EXEC sp_OAMethod @file,'WriteLine',NULL,''
  729.    END
  730.    SET @output = '[' + CAST(@stage as varchar(10)) + '] Delete Old Backup Files...'
  731.    IF @debug = 1 PRINT @output
  732.    IF @report = 1
  733.    BEGIN
  734.       EXEC sp_OAMethod @file,'WriteLine',NULL,@output
  735.    END
  736.  
  737.    DECLARE dcur CURSOR LOCAL FAST_FORWARD
  738.    FOR SELECT dbname FROM #databases ORDER BY dbname
  739.    OPEN dcur
  740.    FETCH NEXT FROM dcur into @database
  741.    WHILE @@FETCH_STATUS=0
  742.    BEGIN
  743.  
  744.       SET @backupfldr = + @backupfldrorig + REPLACE(@database,'''','') + '\'
  745.       SELECT @backupfilename = @backupfldr + REPLACE(REPLACE(@database,' ','_'),'''','_') +
  746.       CASE WHEN UPPER(@optype) = 'DB'   THEN '_FullDBBackup_'
  747.            WHEN UPPER(@optype) = 'DIFF' THEN '_DiffDBBackup_'
  748.            WHEN UPPER(@optype) = 'LOG'  THEN '_LogBackup_'        
  749.       END + @jobstart +
  750.       CASE WHEN UPPER(@optype) = 'LOG' THEN '.TRN' ELSE '.BAK' END
  751.    
  752.       -- load files in @backupfldr
  753.       IF @checkattrib = 1
  754.          SET @cmd = 'dir /B /A-D-A /OD "' + @backupfldr + REPLACE(REPLACE(@database,' ','_'),'''','_') +
  755.          CASE WHEN UPPER(@optype) = 'DB' THEN '_FullDBBackup_'
  756.               WHEN UPPER(@optype) = 'DIFF' THEN '_DiffDBBackup_'
  757.               WHEN UPPER(@optype) = 'LOG'  THEN '_LogBackup_' END + '*' +
  758.          CASE WHEN UPPER(@optype) = 'LOG' THEN '.TRN' ELSE '.BAK' END + '"'
  759.       ELSE
  760.          SET @cmd = 'dir /B /A-D /OD "' + @backupfldr + REPLACE(REPLACE(@database,' ','_'),'''','_') +
  761.          CASE WHEN UPPER(@optype) = 'DB' THEN '_FullDBBackup_'
  762.               WHEN UPPER(@optype) = 'DIFF' THEN '_DiffDBBackup_'
  763.               WHEN UPPER(@optype) = 'LOG'  THEN '_LogBackup_' END + '*' +
  764.          CASE WHEN UPPER(@optype) = 'LOG' THEN '.TRN' ELSE '.BAK' END + '"'
  765.    
  766.       IF @debug = 1 PRINT '@cmd = ' + @cmd
  767.  
  768.       DELETE #files
  769.       INSERT #files EXEC master.dbo.xp_cmdshell @cmd
  770.       DELETE #files WHERE filename IS NULL or filename = ISNULL(REPLACE(@backupfilename,@backupfldr,''),'nothing')
  771.    
  772.       IF @debug = 1 SELECT * FROM #files
  773.      
  774.       -- get count of files that match pattern
  775.       SELECT @filecount = COUNT(*) from #files
  776.       WHERE PATINDEX('%File Not Found%',filename) = 0
  777.       AND PATINDEX('%The system cannot find%',filename) = 0
  778.    
  779.       -- remove files that don't meet retention criteria if there are any files that match pattern
  780.       IF UPPER(@dbretainunit) <> 'COPIES'
  781.       BEGIN
  782.          IF @filecount>0
  783.          BEGIN
  784.             SET @delcmd = N'DELETE #files WHERE DATEADD(' + @datepart + N',' + CAST(@dbretainval as nvarchar(10)) + N',' +
  785.                     'CONVERT(datetime,(SUBSTRING(SUBSTRING(filename,((LEN(filename)-CHARINDEX(''_'',REVERSE(filename)))+2),12),7,2) +''/''
  786.                    + SUBSTRING(SUBSTRING(filename,((LEN(filename)-CHARINDEX(''_'',REVERSE(filename)))+2),12),5,2) +''/''
  787.                    + SUBSTRING(SUBSTRING(filename,((LEN(filename)-CHARINDEX(''_'',REVERSE(filename)))+2),12),1,4) +'' ''
  788.                    + SUBSTRING(SUBSTRING(filename,((LEN(filename)-CHARINDEX(''_'',REVERSE(filename)))+2),12),9,2) +'':''
  789.                    + SUBSTRING(SUBSTRING(filename,((LEN(filename)-CHARINDEX(''_'',REVERSE(filename)))+2),12),11,2)),103)) > ''' + CAST(@jobdt as nvarchar(25)) + N''''
  790.            
  791.             IF @debug = 1 PRINT '@delcmd=' + @delcmd
  792.             EXEC master.dbo.sp_executesql @delcmd
  793.      
  794.             SELECT @delcount = COUNT(*) from #files
  795.          END
  796.          ELSE
  797.          BEGIN
  798.             SELECT @delcount = 0
  799.          END
  800.       END
  801.       ELSE  -- number of copies not date based (include current backup that's not in #files)
  802.       BEGIN
  803.          IF @filecount>0
  804.          BEGIN
  805.             IF @dbretainval>1
  806.             BEGIN
  807.                SET @delcmd = N'DELETE #files WHERE filename IN(SELECT TOP ' + CAST((@dbretainval-1) as nvarchar(10)) +
  808.                              N' filename FROM #files ORDER BY substring(filename,((len(filename)+2)-charindex(''_'',reverse(filename))),12) DESC)'
  809.      
  810.                IF @debug = 1 PRINT '@delcmd=' + @delcmd
  811.                EXEC master.dbo.sp_executesql @delcmd
  812.             END
  813.      
  814.             SELECT @delcount = COUNT(*) from #files
  815.    
  816.          END
  817.          ELSE
  818.          BEGIN
  819.             SELECT @delcount = 0
  820.          END
  821.       END
  822.    
  823.       IF @debug = 1 PRINT '@delcount = ' + STR(@delcount)
  824.    
  825.       -- if there are any matching files
  826.       IF @filecount>0
  827.       BEGIN
  828.          -- are there any files that need deleting
  829.          IF @delcount>0
  830.          BEGIN
  831.             DECLARE FCUR CURSOR FORWARD_ONLY FOR
  832.             SELECT * FROM #files
  833.             OPEN FCUR
  834.             FETCH NEXT FROM FCUR INTO @delfilename
  835.             WHILE @@FETCH_STATUS=0
  836.             BEGIN
  837.                SET @cmd = 'DEL /Q "' + @backupfldr + @delfilename + '"'
  838.                EXEC @cmdret = master.dbo.xp_cmdshell @cmd,no_output  
  839.    
  840.                -- log failure to delete but don't abort procedure
  841.                IF @cmdret<>0
  842.                BEGIN
  843.                   SET @output = SPACE(4) + '*** Error: Failed to delete file ' + @backupfldr + @delfilename + ' ***'
  844.                   IF @debug = 1 PRINT @output
  845.                   IF @report = 1
  846.                   BEGIN
  847.                      EXEC sp_OAMethod @file,'WriteLine',NULL,@output
  848.                   END
  849.                   SELECT @delbkflag = 1 , @cmdret = 0, @delcount = (@delcount-1)
  850.                END
  851.                ELSE
  852.                BEGIN
  853.                   SET @output = SPACE(4) + 'Deleted file ' + @backupfldr + @delfilename
  854.                   IF @debug = 1 PRINT @output
  855.                   IF @report = 1
  856.                   BEGIN
  857.                      EXEC sp_OAMethod @file,'WriteLine',NULL,@output
  858.                   END
  859.                END
  860.    
  861.                FETCH NEXT FROM FCUR INTO @delfilename
  862.             END
  863.             CLOSE FCUR
  864.             DEALLOCATE FCUR
  865.          END
  866.       END
  867.    
  868.       -- write to text report
  869.       SET @output = SPACE(4) + CAST(@delcount as varchar(10)) + ' file(s) deleted.'
  870.       IF @debug = 1 PRINT @output
  871.       IF @report = 1
  872.       BEGIN
  873.          EXEC sp_OAMethod @file,'WriteLine',NULL,@output
  874.          EXEC sp_OAMethod @file,'WriteLine',NULL,''
  875.       END
  876.  
  877.       FETCH NEXT FROM dcur into @database
  878.    END
  879.  
  880.    CLOSE dcur
  881.    DEALLOCATE dcur
  882.  
  883.    -- clear temporary table and variables
  884.    DELETE #files
  885.    SET @cmd = ''
  886.    SET @delcmd = ''
  887.    SET @delfilename = ''
  888.    SET @datepart = ''
  889.    SET @filecount = 0
  890.    SET @delcount = 0
  891.    SET @cmdret = 0
  892.    SET @stage = @stage + 1
  893.  
  894.  
  895.    /************************
  896.       DELETE OLD REPORTS
  897.    ************************/
  898.  
  899.    DELREPORTS:
  900.  
  901.    IF @rptretainunit IS NOT NULL
  902.    BEGIN
  903.       SET @datepart = CASE
  904.          WHEN UPPER(@rptretainunit) = 'MINUTES' THEN N'mi'
  905.          WHEN UPPER(@rptretainunit) = 'HOURS'   THEN N'hh'
  906.          WHEN UPPER(@rptretainunit) = 'DAYS'    THEN N'dd'
  907.          WHEN UPPER(@rptretainunit) = 'WEEKS'   THEN N'ww'
  908.          WHEN UPPER(@rptretainunit) = 'MONTHS'  THEN N'mm'
  909.    END
  910.  
  911.    IF @debug = 1 PRINT '@datepart for reports = ' + @datepart
  912.  
  913.    -- write to text report
  914.    SET @output = '[' + CAST(@stage as varchar(10)) + '] Delete Old Report Files...'
  915.    IF @debug = 1 PRINT @output
  916.    IF @report = 1
  917.    BEGIN
  918.       EXEC sp_OAMethod @file,'WriteLine',NULL,@output
  919.    END
  920.  
  921.    -- load files in @reportfldr
  922.    SET @cmd = 'dir /B /A-D /OD "' + @reportfldr + REPLACE(REPLACE(@databaseorig,' ','_'),'''','') +
  923.    CASE WHEN UPPER(@optype) = 'DB' THEN '_FullDBBackup_report_'
  924.         WHEN UPPER(@optype) = 'DIFF' THEN '_DiffDBBackup_report_'
  925.         WHEN UPPER(@optype) = 'REINDEX'  THEN '_Reindex_report_'    
  926.         WHEN UPPER(@optype) = 'CHECKDB'  THEN '_CheckDB_report_'    
  927.         WHEN UPPER(@optype) = 'REORG'  THEN '_Reorg_report_'
  928.         WHEN UPPER(@optype) = 'LOG'  THEN '_LogBackup_report_' END + '*.txt"'
  929.  
  930.    IF @debug = 1 PRINT '@cmd = ' + @cmd
  931.  
  932.    INSERT #files EXEC master.dbo.xp_cmdshell @cmd
  933.    DELETE #files WHERE filename IS NULL
  934.  
  935.    IF @debug = 1 SELECT * FROM #files
  936.    
  937.    -- get count of files that match pattern
  938.    SELECT @filecount = COUNT(*) from #files
  939.    WHERE PATINDEX('%File Not Found%',filename) = 0
  940.    AND PATINDEX('%The system cannot find%',filename) = 0
  941.  
  942.    -- remove files that don't meet retention criteria if there are any files that match pattern
  943.    IF UPPER(@rptretainunit) <> 'COPIES'
  944.    BEGIN
  945.       IF @filecount>0
  946.       BEGIN
  947.          SET @delcmd = N'DELETE #files WHERE DATEADD(' + @datepart + N',' + CAST(@rptretainval as nvarchar(10)) + N',' +
  948.                  'CONVERT(datetime,(SUBSTRING(SUBSTRING(filename,((LEN(filename)-CHARINDEX(''_'',REVERSE(filename)))+2),12),7,2) +''/''
  949.                 + SUBSTRING(SUBSTRING(filename,((LEN(filename)-CHARINDEX(''_'',REVERSE(filename)))+2),12),5,2) +''/''
  950.                 + SUBSTRING(SUBSTRING(filename,((LEN(filename)-CHARINDEX(''_'',REVERSE(filename)))+2),12),1,4) +'' ''
  951.                 + SUBSTRING(SUBSTRING(filename,((LEN(filename)-CHARINDEX(''_'',REVERSE(filename)))+2),12),9,2) +'':''
  952.                 + SUBSTRING(SUBSTRING(filename,((LEN(filename)-CHARINDEX(''_'',REVERSE(filename)))+2),12),11,2)),103)) > ''' + CAST(@jobdt as nvarchar(25)) + N''''
  953.          
  954.          IF @debug = 1 PRINT '@delcmd=' + @delcmd
  955.          EXEC master.dbo.sp_executesql @delcmd
  956.    
  957.          SELECT @delcount = COUNT(*) from #files
  958.       END
  959.       ELSE
  960.       BEGIN
  961.          SELECT @delcount = 0
  962.       END
  963.    END
  964.    ELSE  -- number of copies not date based
  965.    BEGIN
  966.       IF @filecount>0
  967.       BEGIN
  968.          SET @delcmd = N'DELETE #files WHERE filename IN(SELECT TOP ' + CAST(@rptretainval as nvarchar(10)) +
  969.                        N' filename FROM #files ORDER BY substring(filename,((len(filename)+2)-charindex(''_'',reverse(filename))),12) DESC)'
  970.  
  971.          IF @debug = 1 PRINT '@delcmd=' + @delcmd
  972.          EXEC master.dbo.sp_executesql @delcmd
  973.    
  974.          SELECT @delcount = COUNT(*) from #files
  975.       END
  976.       ELSE
  977.       BEGIN
  978.          SELECT @delcount = 0
  979.       END
  980.    END
  981.    
  982.    IF @debug = 1 PRINT STR(@delcount)
  983.  
  984.    -- if there are any matching files
  985.    IF @filecount>0
  986.    BEGIN
  987.       -- are there any files that need deleting
  988.       IF @delcount>0
  989.       BEGIN
  990.          DECLARE FCUR CURSOR FORWARD_ONLY FOR
  991.          SELECT * FROM #files
  992.          OPEN FCUR
  993.          FETCH NEXT FROM FCUR INTO @delfilename
  994.          WHILE @@FETCH_STATUS=0
  995.          BEGIN
  996.             SET @cmd = 'DEL /Q "' + @reportfldr + @delfilename + '"'
  997.             EXEC @cmdret = master.dbo.xp_cmdshell @cmd,no_output  
  998.  
  999.             -- log failure to delete but don't abort procedure
  1000.             IF @cmdret<>0
  1001.             BEGIN
  1002.  
  1003.                SET @output = SPACE(4) + '*** Error: Failed to delete file ' + @reportfldr + @delfilename + ' ***'
  1004.                IF @debug = 1 PRINT @output
  1005.                IF @report = 1
  1006.                BEGIN
  1007.                   EXEC sp_OAMethod @file,'WriteLine',NULL,@output
  1008.                END
  1009.                SELECT @delrptflag = 1 , @cmdret = 0, @delcount = (@delcount-1)
  1010.             END
  1011.             BEGIN
  1012.                SET @output = SPACE(4) + 'Deleted file ' + @reportfldr + @delfilename
  1013.                IF @debug = 1 PRINT @output
  1014.                IF @report = 1
  1015.                BEGIN
  1016.                   EXEC sp_OAMethod @file,'WriteLine',NULL,@output
  1017.                END
  1018.             END
  1019.  
  1020.             FETCH NEXT FROM FCUR INTO @delfilename
  1021.          END
  1022.          CLOSE FCUR
  1023.          DEALLOCATE FCUR
  1024.       END
  1025.    END
  1026.  
  1027.    -- write to text report
  1028.    SET @output = SPACE(4) + CAST(@delcount as varchar(10)) + ' file(s) deleted.'
  1029.    IF @debug = 1 PRINT @output
  1030.    IF @report = 1
  1031.    BEGIN
  1032.       EXEC sp_OAMethod @file,'WriteLine',NULL,@output
  1033.       EXEC sp_OAMethod @file,'WriteLine',NULL,''
  1034.    END
  1035.  
  1036.    -- update stage
  1037.    SET @stage = @stage + 1
  1038.    END
  1039.    -- if we got here due to @delfirst = 1 go back and do the backups
  1040.    IF @delfirst = 1
  1041.       GOTO DOBACKUP
  1042.    ELSE
  1043.       GOTO CLEANUP
  1044.  
  1045.  
  1046. /************************
  1047.          CHECKDB
  1048. ************************/
  1049.  
  1050.    CHECK_DB:
  1051.  
  1052.    IF @optype = 'CHECKDB'
  1053.    BEGIN
  1054.  
  1055.       DECLARE dcur CURSOR LOCAL FAST_FORWARD
  1056.       FOR SELECT dbname FROM #databases ORDER BY dbname
  1057.       OPEN dcur
  1058.       FETCH NEXT FROM dcur into @database
  1059.       WHILE @@FETCH_STATUS=0
  1060.       BEGIN
  1061.  
  1062.          -- write to text report
  1063.          IF @report = 1
  1064.          BEGIN
  1065.             EXEC sp_OAMethod @file,'WriteLine',NULL,''
  1066.             SET @output = '[' + CAST(@stage as varchar(10)) + '] Database ' + @database + ': Check Data and Index Linkage...'
  1067.             IF @debug = 1 PRINT @output
  1068.             EXEC sp_OAMethod @file,'WriteLine',NULL,@output  
  1069.          END
  1070.  
  1071.          -- set backup start time
  1072.          SET @start = GETDATE()
  1073.  
  1074.          SET @execmd = N'DBCC CHECKDB([' + @database + N']) WITH NO_INFOMSGS'
  1075.          IF @debug = 1 PRINT 'DBCC Command : ' + @execmd
  1076.          
  1077.          BEGIN TRY
  1078.  
  1079.             EXEC(@execmd)
  1080.  
  1081.          END TRY
  1082.          BEGIN CATCH
  1083.  
  1084.             SELECT @err = @@ERROR,@ret = @err
  1085.             SET @errormsg = 'CheckDB of ' + @database + ' failed with Native Error : ' + CAST(@err as varchar(10))
  1086.             SET @output = SPACE(4) + '*** ' + @errormsg + ' ***'
  1087.             PRINT @output
  1088.             IF @report = 1
  1089.             BEGIN
  1090.                EXEC sp_OAMethod @file,'WriteLine',NULL,@output
  1091.             END
  1092.  
  1093.         IF @continue_on_error <> 1
  1094.         BEGIN
  1095.             CLOSE dcur
  1096.             DEALLOCATE dcur
  1097.             GOTO CLEANUP
  1098.         END  
  1099.  
  1100.          END CATCH
  1101.          
  1102.          SET @finish = GETDATE()
  1103.  
  1104.          --calculate checkdb runtime
  1105.          SET @runtime = (@finish - @start)
  1106.          SET @output = SPACE(4) + 'CheckDB completed in '
  1107.                      + CAST(DATEPART(hh,@runtime) as varchar(2)) + ' hour(s) '
  1108.                      + CAST(DATEPART(mi,@runtime) as varchar(2)) + ' min(s) '
  1109.                      + CAST(DATEPART(ss,@runtime) as varchar(2)) + ' second(s)'
  1110.          IF @debug = 1 PRINT @output
  1111.          IF @report = 1
  1112.          BEGIN
  1113.             EXEC sp_OAMethod @file,'WriteLine',NULL,@output
  1114.             EXEC sp_OAMethod @file,'WriteLine',NULL,''
  1115.          END  
  1116.          SET @stage = (@stage + 1)
  1117.          FETCH NEXT FROM dcur into @database      
  1118.      
  1119.       END
  1120.  
  1121.       CLOSE dcur
  1122.       DEALLOCATE dcur
  1123.      
  1124.       -- delete reports
  1125.       IF @report = 1
  1126.       BEGIN
  1127.          EXEC sp_OAMethod @file,'WriteLine',NULL,''
  1128.       END
  1129.       GOTO DELREPORTS
  1130.    END
  1131.  
  1132. /************************
  1133.      REINDEX/REORG
  1134. ************************/
  1135.  
  1136.    REINDEX:
  1137.  
  1138.    IF @optype in ('REINDEX','REORG')
  1139.    BEGIN
  1140.  
  1141.       DECLARE dcur CURSOR LOCAL FAST_FORWARD
  1142.       FOR SELECT dbname FROM #databases ORDER BY dbname
  1143.       OPEN dcur
  1144.       FETCH NEXT FROM dcur into @database
  1145.       WHILE @@FETCH_STATUS=0
  1146.       BEGIN
  1147.  
  1148.          -- write to text report
  1149.          IF @report = 1
  1150.          BEGIN
  1151.             EXEC sp_OAMethod @file,'WriteLine',NULL,''
  1152.             IF @optype = 'REINDEX'
  1153.                SET @output = '[' + CAST(@stage as varchar(10)) + '] Database ' + @database + ': Index Rebuild (using original fillfactor)...'
  1154.             ELSE
  1155.                SET @output = '[' + CAST(@stage as varchar(10)) + '] Database ' + @database + ': Index Reorganize...'
  1156.  
  1157.             IF @debug = 1 PRINT @output
  1158.             EXEC sp_OAMethod @file,'WriteLine',NULL,@output  
  1159.             EXEC sp_OAMethod @file,'WriteLine',NULL,''  
  1160.          END
  1161.  
  1162.          -- set start time
  1163.          SET @start = GETDATE()
  1164.  
  1165.          -- all user tables
  1166.          CREATE TABLE #tables(tablename sysname)
  1167.          EXEC(N'INSERT #tables(tablename) SELECT DISTINCT(''['' + s.[name] + ''].['' + t.[name] + '']'') FROM [' + @database + N'].sys.tables t ' +
  1168.               N'JOIN [' + @database + N'].sys.schemas s on t.schema_id=s.schema_id ' +
  1169.               N'JOIN [' + @database + N'].sys.indexes i on t.object_id=i.object_id ' +
  1170.               N'WHERE t.is_ms_shipped = 0 AND i.type>0')
  1171.  
  1172.          DECLARE tcur CURSOR LOCAL FAST_FORWARD
  1173.          FOR SELECT tablename FROM #tables ORDER BY tablename
  1174.          OPEN tcur
  1175.          FETCH NEXT FROM tcur INTO @table
  1176.          WHILE @@FETCH_STATUS = 0
  1177.          BEGIN
  1178.  
  1179.             IF @report = 1
  1180.             BEGIN
  1181.                IF @optype = 'REINDEX'
  1182.                   SET @output = SPACE(4) + N'Rebuilding indexes for table ' + @table
  1183.                ELSE
  1184.                   SET @output = SPACE(4) + N'Reorganizing indexes for table ' + @table
  1185.  
  1186.                EXEC sp_OAMethod @file,'WriteLine',NULL,@output
  1187.             END  
  1188.  
  1189.            
  1190.             IF @optype = 'REINDEX'
  1191.                SET @execmd = N'ALTER INDEX ALL ON [' + @database + N'].' + @table + N' REBUILD'
  1192.             ELSE
  1193.                SET @execmd = N'ALTER INDEX ALL ON [' + @database + N'].' + @table + N' REORGANIZE'
  1194.    
  1195.             IF @debug = 1 PRINT 'Reindex Command : ' + @execmd
  1196.  
  1197.             BEGIN TRY
  1198.    
  1199.                EXEC(@execmd)
  1200.    
  1201.             END TRY
  1202.             BEGIN CATCH
  1203.            
  1204.                SELECT @err = @@ERROR,@ret = @err
  1205.                SET @errormsg = 'Rebuild of indexes on [' + @database + N'].' + @table + ' failed with Native Error : ' + CAST(@err as varchar(10))
  1206.                SET @output = SPACE(4) + '*** ' + @errormsg + ' ***'
  1207.                PRINT @output
  1208.                IF @report = 1
  1209.                BEGIN
  1210.                   EXEC sp_OAMethod @file,'WriteLine',NULL,@output
  1211.                END
  1212.  
  1213.  
  1214.             IF @continue_on_error <> 1
  1215.             BEGIN
  1216.                CLOSE tcur
  1217.                DEALLOCATE tcur
  1218.                DROP TABLE #tables
  1219.                GOTO CLEANUP
  1220.             END  
  1221.             END CATCH
  1222.  
  1223.             FETCH NEXT FROM tcur INTO @table
  1224.          END
  1225.  
  1226.          CLOSE tcur
  1227.          DEALLOCATE tcur
  1228.    
  1229.          SET @finish = GETDATE()
  1230.  
  1231.          --calculate runtime
  1232.          SET @runtime = (@finish - @start)
  1233.          SET @output = SPACE(4) + 'Index maintenance completed in '
  1234.                      + CAST(DATEPART(hh,@runtime) as varchar(2)) + ' hour(s) '
  1235.                      + CAST(DATEPART(mi,@runtime) as varchar(2)) + ' min(s) '
  1236.                      + CAST(DATEPART(ss,@runtime) as varchar(2)) + ' second(s)'
  1237.          IF @debug = 1 PRINT @output
  1238.          IF @report = 1
  1239.          BEGIN
  1240.             EXEC sp_OAMethod @file,'WriteLine',NULL,''
  1241.             EXEC sp_OAMethod @file,'WriteLine',NULL,@output
  1242.             EXEC sp_OAMethod @file,'WriteLine',NULL,''
  1243.          END  
  1244.  
  1245.          DROP TABLE #tables
  1246.  
  1247.          SET @stage = (@stage + 1)
  1248.          FETCH NEXT FROM dcur into @database  
  1249.      
  1250.       END
  1251.  
  1252.       CLOSE dcur
  1253.       DEALLOCATE dcur
  1254.      
  1255.       -- delete reports
  1256.       GOTO DELREPORTS
  1257.    END
  1258.  
  1259.      
  1260. /************************
  1261.          CLEAN UP
  1262. ************************/
  1263.  
  1264.    CLEANUP:
  1265.  
  1266.    DROP TABLE #files
  1267.    DROP TABLE #exists
  1268.    DROP TABLE #databases
  1269.  
  1270.    -- if we encountered errors deleting old backups return failure
  1271.    IF @delbkflag<>0
  1272.    BEGIN
  1273.       SET @errormsg = 'Expressmaint encountered errors deleting old backup files' + CHAR(13)
  1274.                     + CASE WHEN @report = 1 THEN ('Please see ' + @reportfilename + CHAR(13) + ' for further details') ELSE '' END
  1275.       RAISERROR(@errormsg,16,1)
  1276.       SET @ret = 1
  1277.    END
  1278.  
  1279.    -- if we encountered errors deleting old reports return failure
  1280.    IF (@delrptflag<>0 AND @delbkflag = 0)
  1281.    BEGIN
  1282.       SET @errormsg = 'Expressmaint encountered errors deleting old report files' + CHAR(13)
  1283.                     + CASE WHEN @report = 1 THEN ('Please see ' + @reportfilename + CHAR(13) + ' for further details') ELSE '' END
  1284.       RAISERROR(@errormsg,16,1)
  1285.       SET @ret = 1
  1286.    END
  1287.    
  1288.    -- if we created a file make sure we write trailer and destroy object
  1289.    IF @filecrt = 1
  1290.    BEGIN
  1291.       -- write final part of report
  1292.       EXEC sp_OAMethod @file,'WriteLine',NULL,''
  1293.       SET @output = 'Expressmaint processing finished at ' + CONVERT(varchar(25),GETDATE(),100)
  1294.                   + ' (Return Code : ' + CAST(@ret as varchar(10)) + ')'
  1295.       IF @debug = 1 PRINT @output
  1296.       EXEC sp_OAMethod @file,'WriteLine',NULL,@output
  1297.       EXEC sp_OAMethod @file,'WriteLine',NULL,''
  1298.  
  1299.       -- destroy file object
  1300.       EXEC @hr=sp_OADestroy @file
  1301.       IF @hr <> 0 EXEC sp_OAGetErrorInfo @file
  1302.    END
  1303.  
  1304.    IF @report = 1
  1305.    BEGIN
  1306.       EXEC @hr=sp_OADestroy @fso
  1307.       IF @hr <> 0 EXEC sp_OAGetErrorInfo @fso
  1308.    END
  1309.  
  1310. RETURN @ret
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement