Check for full SQL Server database backups before creating other backups
For very large databases, we usually include either differential, file or filegroup backups together with the full database backup in our backup plan. In some cases, differential backups are used before a major change is implemented in the database. The backups can, then, be used to rollback those changes if and when necessary. The challenge with using these other types of backups is that they require a full backup as the starting point for the restore process. How do we make sure that we have a copy of the full database backups before we generate these other types of backups?
In a previous tip on Differential Database Backups for SQL Server, you have seen how differential backups work in combination with full database backups. However, you need to make sure that, if you are generating differential backups or any other type of backups other than the full database backup, the full database backup should be available. This is specifically helpful in cases where you would need to implement a major change in your database and would like to have a backup available for rollback purposes in case the need arise. I have seen organizations where they do not have the benefits of having database snapshots in SQL Server for rollback purposes. As this is an Enterprise Edition-only feature, they would opt to use both a full and differential backups for the purpose of rolling back changes.
The script below will create a stored procedure that is used to generate differential backups. You can also change it to any other type of backups but, for the purpose of this tip, I will be using a differential backup.
The stored procedure works by checking the backup history and searches for the latest full database backup and the corresponding file. If the latest full database backup does not exist or the database has never been backed up, the differential backup will abort. The stored procedure accepts a parameter that will contain the location of the differential backup with a default value of your pre-defined backup location.
CREATE PROCEDURE sp_generateDifferentialBackups @strBackupPath NVARCHAR (25) ='D:\backups\' --variable for location of DIFFERENTIAL backups AS SET NOCOUNT ON -- Get the name of all user databases DECLARE @strTimeStamp NVARCHAR(12) --variable for timestamp value DECLARE @strSQL NVARCHAR(100) -- used for generating dynamic SQL statements DECLARE @databaseName NVARCHAR(128) -- used as variable to store database names DECLARE dbCursor CURSOR FOR -- used for cursor allocation SELECT NAME FROM MASTER.SYS.DATABASES WHERE [database_id] > 0 AND NAME NOT IN ('MASTER','MODEL','MSDB','TEMPDB') --does not include the system databases OPEN dbCursor FETCH NEXT FROM dbCursor INTO @databaseName WHILE (@@FETCH_STATUS = 0) BEGIN PRINT 'Checking for the latest FULL database backup for: [' + @databaseName +']' DECLARE @strphysical_device_name NVARCHAR(100) -- variable for physical_device_name DECLARE @cursor NVARCHAR(400) -- Reads the MSDB database to check for the latest FULL database backup SELECT @cursor=('DECLARE TabCursor CURSOR FAST_FORWARD GLOBAL FOR ' + 'SELECT TOP 1 physical_device_name FROM msdb.dbo.backupset a INNER JOIN msdb.dbo.backupmediafamily b ON a.media_set_id = b.media_set_id WHERE database_name=''' + @databaseName + ''' AND type=''D'' ORDER BY backup_finish_date desc') EXEC sp_executesql @cursor OPEN TabCursor FETCH NEXT FROM TabCursor INTO @strphysical_device_name --Check if the database does not have any FULL backups at all IF @@FETCH_STATUS <> 0 BEGIN PRINT '*****WARNING: Database [' + @databaseName + '] does not have any FULL database backups at all. Generate the FULL database backup first. Aborting DIFFERENTIAL backup command.*****' END ELSE --If the database has FULL backups, WHILE @@FETCH_STATUS = 0 BEGIN DECLARE @result INT EXEC xp_fileexist @strphysical_device_name, @result output IF (@result = 1) --@result will return 1 if the specified file exists, if it doesn't, it will return 0 BEGIN SET @strTimeStamp=CONVERT(CHAR(8), GETDATE(), 112) SET @strTimeStamp=@strTimeStamp + REPLACE(CONVERT(CHAR(8), GETDATE(), 108),':','') EXEC ('BACKUP DATABASE ' + @databaseName + ' TO DISK=''' + @strBackupPath + @databaseName + '_DIFF_' + @strTimeStamp + '.BAK'' WITH INIT, DIFFERENTIAL, DESCRIPTION=''DIFFERENTIAL Backup for ' + @databasename + ' database''') -- change this value should you decide to change the backup type to something other than differential PRINT '===========================================================================================' PRINT 'DIFFERENTIAL Backup generated for database: [' + @databaseName + ']' PRINT 'Corresponding FULL database backup: ' + @strphysical_device_name PRINT 'DIFFERENTIAL database backup: ' + @strBackupPath + @databaseName + '_DIFF_' + @strTimeStamp + '.BAK' END ELSE PRINT '*********WARNING: FULL database backup file is missing. Generate the FULL database backup first. Aborting DIFFERENTIAL backup command.*********' FETCH NEXT FROM TabCursor INTO @strphysical_device_name END CLOSE TabCursor DEALLOCATE TabCursor PRINT '===========================================================================================' PRINT ' ' PRINT ' ' PRINT ' ' FETCH NEXT FROM dbCursor INTO @databaseName END CLOSE dbCursor DEALLOCATE dbCursor PRINT 'FINISHED' GO
You can either pass a parameter that contains the backup location where you intend to store the differential backup or simply call the stored procedure as it is.
Here sample output after creating and running the stored procedure.
Aside from using this stored procedure to generate ad-hoc differential backups, this can also be used as an alternative to your database maintenance plans. Instead of using the Backup Database Task, you can use an Execute TSQL Task and call this stored procedure. By doing so, you are practically sure that your differential backups will have their corresponding full database backups. You can customize this script to send alerts when the differential backup is aborted to let you know that you either have a missing full database backup or that your database has not been backed up yet.
- Read the tip on Differential Database Backups for SQL Server
- Evaluate the use of differential backups in your backup strategy and use this script to generate the differential backups
About the author
View all my tips