SQL Cursor

Sara 441 Reputation points
2023-11-21T10:42:48.9133333+00:00

I have a T-sql script to automate the backup process where our Full and differential backups are backed up using that script and striped based on size, where I need some help to update the existing Script to add another backup (Tlog) with extension .trn

 CREATE TABLE #DbSizeWithNoFreeSpace (
    SELECT [Database_Name],
        CEILING(CAST(DB_Used AS DECIMAL) / 1024.0) AS DBSpaceUsedGB,
        NULL AS [Ratio],
        NULL AS [filecount]
    INTO #DbSizeWithfilecount
    FROM #DbSizeWithNoFreeSpace
    WHERE [Database_Name] NOT IN ('tempdb')
 
    -- Declare variables to use when calculating our ratio and backup file values
    DECLARE @CurrentDBName VARCHAR(50),
        @CurrentDBSpaceUsedGB INT,
        @Ratio INT,
        @filecount1 INT,
        @MaxFileSizeGB INT,
        @MinDBSizeInRatioTable INT
 
    -- Grab our max file size that we'd make a backup file (Azure blob storage has 200 GB limit for block blobs)
    SET @MaxFileSizeGB = (
            SELECT MaxFileSizeGB
            FROM [zsqdbadb].[dbo].[dbaDatabaseBackupDrive] where DatabaseName is NULL and ExcludeBackupInd is NULL
            )
 
    -- Grab the minimum size from our ratio table
    SELECT @MinDBSizeInRatioTable = MIN(DBSize)
    FROM zsqdbadb.dbo.dbaDatabaseBackupRatio_t
 
    -- Declare a cursor using the data from our DBSizefilecount that we'll iterate through
    DECLARE database_filecount_cursor CURSOR
    FOR
    SELECT [Database_name],
        DBSpaceUsedGB,
        Ratio,
        filecount
    FROM #DbSizeWithfilecount
 
    -- Open the cursor
    OPEN database_filecount_cursor
 
    -- Grab the first record and load the values of it's columns in the variables we declared
    FETCH NEXT
    FROM database_filecount_cursor
    INTO @CurrentDBName,
        @CurrentDBSpaceUsedGB,
        @Ratio,
        @filecount1
 
    -- Start our loop through the cursor
    WHILE @@FETCH_STATUS = 0
    BEGIN
        -- Grab the 1st ratio from our look up table that's LESS THAN OR EQUAL to the current DB's space used when we look
        SELECT TOP 1 @Ratio = RatioNumber
        FROM zsqdbadb.dbo.dbaDatabaseBackupRatio_t
        WHERE DBSize <= @CurrentDBSpaceUsedGB
        ORDER BY DBSize DESC
 
        -- Check and see if @Ratio is null, this could be because the current DB size is less than our smallest record in our ratio table
        IF (@Ratio IS NULL)
        BEGIN
            IF (@CurrentDBSpaceUsedGB <= @MinDBSizeInRatioTable)
            BEGIN
                SELECT @Ratio = RatioNumber
                FROM zsqdbadb.dbo.dbaDatabaseBackupRatio_t
                WHERE DBSize = @MinDBSizeInRatioTable
            END
        END
 
        --Calculate our backup files using our formula, note we CAST to ensure we get a minimum of 1 backup file
        SELECT @filecount1 = CEILING(CAST(@CurrentDBSpaceUsedGB AS DECIMAL) / CAST(@MaxFileSizeGB AS DECIMAL) / @Ratio)
 
        --Now that we have our values, let's populate the ratio and backup files for the current database we're iterating through
        UPDATE #DbSizeWithfilecount
        SET ratio = @ratio,
            filecount = @filecount1
        WHERE [Database_Name] = @CurrentDBName
 
        -- Get the next database from the cursor
        FETCH NEXT
        FROM database_filecount_cursor
        INTO @CurrentDBName,
            @CurrentDBSpaceUsedGB,
            @ratio,
            @filecount1
    END
 
    CLOSE database_filecount_cursor;
    DEALLOCATE database_filecount_cursor;
 
    UPDATE @db
    SET fileCount = #DbSizeWithfilecount.filecount
    FROM @db AS D
    INNER JOIN #DbSizeWithfilecount ON (D.dbName = #DbSizeWithfilecount.Database_Name)
 
    -- Clean up our temp tables
    DROP TABLE #DbSizeWithNoFreeSpace
    DROP TABLE #DbSizeWithfilecount
 
    -- *End of code block that calculated how many backup files (filecount) to be used for each database and updated the table variable @db* --
    -- Distribute files evenly among available drives
    UPDATE @db
    SET fileCount = CASE
            WHEN fileCount = 1
                THEN 1
            WHEN fileCount > coalesce(@maxFileCount, (32 / driveCount) * driveCount)
                THEN (coalesce(@maxFileCount, (32 / driveCount) * driveCount) / driveCount) * driveCount
            ELSE CASE
                    WHEN fileCount % driveCount = 0
                        THEN fileCount
                    ELSE ((fileCount / driveCount) + 1) * driveCount
                    END
            END
 
    --Debug
    --SELECT * FROM @db
    DECLARE c1 CURSOR
    FOR
    SELECT T.dbName,
        T.backupType,
        T.lastFull,
        T.drive01,
        T.drive02,
        T.drive03,
        T.drive04,
        T.drive05,
        T.drive06,
        T.drive07,
        T.drive08,
        T.drive09,
        T.drive10,
        T.drive11,
        T.drive12,
        T.drive13,
        T.drive14,
        T.drive15,
        T.drive16,
        T.driveCount,
        T.fileCount,
        T.clevel,
        T.retention,
        T.folder
    FROM @db T
    WHERE backupType IS NOT NULL
 
    OPEN c1
 
    FETCH NEXT
    FROM c1
    INTO @dbName,
        @backupType,
        @lastFull,
        @drive01,
        @drive02,
        @drive03,
        @drive04,
        @drive05,
        @drive06,
        @drive07,
        @drive08,
        @drive09,
        @drive10,
        @drive11,
        @drive12,
        @drive13,
        @drive14,
        @drive15,
        @drive16,
        @driveCount,
        @fileCount,
        @clevel,
        @retention,
        @folder
 
    WHILE @@fetch_status = 0
    BEGIN
        IF @folder IS NULL
            SET @_folder = '\SQL_Backup' + @instance + '\'
        ELSE IF @_drive01 LIKE 'http://%'
            OR @_drive01 LIKE 'https://%'
        BEGIN
            SET @_folder = rtrim(ltrim(@_folder))
 
            IF left(@_folder, 1) <> '/'
                SET @_folder = '/' + @_folder
 
            IF right(@_folder, 1) <> '/'
                SET @_folder = @_folder + '/'
        END
        ELSE
        BEGIN
            SET @_folder = rtrim(ltrim(@_folder))
 
            IF left(@_folder, 1) <> '\'
                SET @_folder = '\' + @_folder
 
            IF right(@_folder, 1) <> '\'
                SET @_folder = @_folder + '\'
        END
 
        IF @driveCount >= 1
        BEGIN
            SET @drive01 = @drive01 + @folder
 
            IF @driveCount >= 2
            BEGIN
                SET @drive02 = @drive02 + @folder
 
                IF @driveCount >= 3
                BEGIN
                    SET @drive03 = @drive03 + @folder
 
                    IF @driveCount >= 4
                    BEGIN
                        SET @drive04 = @drive04 + @folder
 
                        IF @driveCount >= 5
                        BEGIN
                            SET @drive05 = @drive05 + @folder
 
                            IF @driveCount >= 6
                            BEGIN
                                SET @drive06 = @drive06 + @folder
 
                                IF @driveCount >= 7
                                BEGIN
                                    SET @drive07 = @drive07 + @folder
 
                                    IF @driveCount >= 8
                                    BEGIN
                                        SET @drive08 = @drive08 + @folder
 
                                        IF @driveCount >= 9
                                        BEGIN
                                            SET @drive09 = @drive09 + @folder
 
                                            IF @driveCount >= 10
                                            BEGIN
                                                SET @drive10 = @drive10 + @folder
 
                                                IF @driveCount >= 11
                                                BEGIN
                                                    SET @drive11 = @drive11 + @folder
 
                                                    IF @driveCount >= 12
                                                    BEGIN
                                                        SET @drive12 = @drive12 + @folder
 
                                                        IF @driveCount >= 13
                                                        BEGIN
                                                            SET @drive13 = @drive13 + @folder
 
                                                            IF @driveCount >= 14
                                                            BEGIN
                                                                SET @drive14 = @drive14 + @folder
 
                                                                IF @driveCount >= 15
                                                                BEGIN
                                                                    SET @drive15 = @drive15 + @folder
 
                                                                    IF @driveCount >= 16
                                                                    BEGIN
                                                                        SET @drive16 = @drive16 + @folder
                                                                    END
                                                                END
                                                            END
                                                        END
                                                    END
                                                END
                                            END
                                        END
                                    END
                                END
                            END
                        END
                    END
                END
            END
        END
 
        SET @command = 'BACKUP ' + CASE @backupType
                WHEN 'T'
                    THEN 'LOG'
                ELSE 'DATABASE'
                END + ' [' + @dbName + '] TO '
 
        IF @backupType IN ('F', 'D')
        BEGIN
            SELECT @fileN = 1,
                @driveL = CASE @driveCount
                    WHEN 1
                        THEN @drive01
                    WHEN 2
                        THEN @drive02
                    WHEN 3
                        THEN @drive03
                    WHEN 4
                        THEN @drive04
                    WHEN 5
                        THEN @drive05
                    WHEN 6
                        THEN @drive06
                    WHEN 7
                        THEN @drive07
                    WHEN 8
                        THEN @drive08
                    WHEN 9
                        THEN @drive09
                    WHEN 10
                        THEN @drive10
                    WHEN 11
                        THEN @drive11
                    WHEN 12
                        THEN @drive12
                    WHEN 13
                        THEN @drive13
                    WHEN 14
                        THEN @drive14
                    WHEN 15
                        THEN @drive15
                    WHEN 16
                        THEN @drive16
                    END
 
            WHILE @fileN <= @fileCount
            BEGIN
                SET @driveS = CASE @fileN % @driveCount
                        WHEN 0
                            THEN @driveL
                        WHEN 1
                            THEN @drive01
                        WHEN 2
                            THEN @drive02
                        WHEN 3
                            THEN @drive03
                        WHEN 4
                            THEN @drive04
                        WHEN 5
                            THEN @drive05
                        WHEN 6
                            THEN @drive06
                        WHEN 7
                            THEN @drive07
                        WHEN 8
                            THEN @drive08
                        WHEN 9
                            THEN @drive09
                        WHEN 10
                            THEN @drive10
                        WHEN 11
                            THEN @drive11
                        WHEN 12
                            THEN @drive12
                        WHEN 13
                            THEN @drive13
                        WHEN 14
                            THEN @drive14
                        WHEN 15
                            THEN @drive15
                        WHEN 16
                            THEN @drive16
                        END
 
                IF (
                        @_drive01 LIKE 'https://%'
                        OR @_drive01 LIKE 'http://%'
                        )
                BEGIN
                    SET @command = @command + @crlf + CASE @fileN
                            WHEN 1
                                THEN ' '
                            ELSE ','
                            END + 'URL = ''' + @driveS + @dbName + '/' + @dbname + '_' + @backupDT + '_' + CASE @backupType
                            WHEN 'F'
                                THEN 'FULL'
                            ELSE 'DIFF'
                            END + CASE @fileCount
                            WHEN 1
                                THEN ''
                            ELSE '_' + right('0' + cast(@fileN AS VARCHAR(2)), 2)
                            END + '.bak'''
                    SET @fileN = @fileN + 1
                END
                ELSE
                BEGIN
                    SET @createfolder = @driveS + @dbName
                    SET @MD = 'mkdir' + @createfolder
                    EXEC master..xp_cmdshell @MD, no_output
                    SET @createfolder = @createfolder + '\'
                    SET @command = @command + @crlf + CASE @fileN
                            WHEN 1
                                THEN ' '
                            ELSE ','
                            END + 'DISK = ''' + @createfolder + @dbname + '_' + @backupDT + '_' + CASE @backupType
                            WHEN 'F'
                                THEN 'FULL'
                            ELSE 'DIFF'
                            END + CASE @fileCount
                            WHEN 1
                                THEN ''
                            ELSE '_' + right('0' + cast(@fileN AS VARCHAR(2)), 2)
                            END + '.bak'''
                    SET @fileN = @fileN + 1
                END
            END
 
            SET @command = @command + @crlf + ' WITH COMPRESSION, MAXTRANSFERSIZE = 4194304, BLOCKSIZE = 65536, CHECKSUM, STATS = 5, NAME = N''' + @dbName + ' - ' + CASE @backupType
                    WHEN 'F'
                        THEN 'FULL backup''' + ', RETAINDAYS = ' + CAST(@_fretentiondays AS VARCHAR(2))
                    WHEN 'D'
                        THEN 'DIFFERENTIAL database backup''' + ', DIFFERENTIAL, RETAINDAYS = ' + CAST(@_dretentiondays AS VARCHAR(2))
                    END
        END
        ELSE IF (
                @_drive01 LIKE 'https://%'
                OR @_drive01 LIKE 'http://%'
                )
        BEGIN
            SET @command = @command + @crlf + 'URL = ''' + @drive01 + @dbName + '/' + @dbname + '_' + @backupDT + '_' + 'TLOG.trn''' +
                --'DISK = ''' + @drive01 +@dbname +'_' +'LOG.trn'''+
                ' WITH RETAINDAYS = ' + CAST(@_tretentiondays AS VARCHAR(3)) + ',COMPRESSION, NAME = N''' + @dbName + ' - ' + 'TLOG backup'''
        END
        ELSE
        BEGIN
            SET @command = @command + @crlf + 'DISK = ''' + @drive01 + @dbName + '\' + @dbname + '_' + @backupDT + '_' + 'TLOG.trn''' +
                --'DISK = ''' + @drive01 +@dbname +'_' +'LOG.trn'''+
                ' WITH RETAINDAYS = ' + CAST(@_tretentiondays AS VARCHAR(3)) + ',COMPRESSION, NAME = N''' + @dbName + ' - ' + 'TLOG backup'''
        END
Developer technologies Transact-SQL
SQL Server Other
0 comments No comments
{count} votes

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.