Technical Article

Dynamic Database Backup

,

Have you ever added a database to the server and forgot to add it to the backup plan? Now you don't have to worry about that task. This procedure uses the database names from sys.databases and backs each database up to a local drive. Only a few things are required. 1) A local drive, 2) DB Mail, mail profile and recipient. (or comment out the mail section), and 3) the ability to execute xp_create_subdir. A SQL Agent job can call this procedure on a predefined schedule and you never miss a database backup again.

-------------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------------
-- This procedure was written to facilitate the backing up of the databases on this server. 
-- Many times new databases are created and the backup procedures forgotten to be 
-- modified to include the new databases. This procedure will back up the databases
-- to the specified root folder/instancename/database/data with a name of
-- DatabaseName_YYYY_MM_DD_HH_MM_SS.bak 
--
-- This procedure requires DB Mail to be configured to receive error notifications.
-- The profile name i use is 'SQL Backup Mail'
--
-- Author: Mitchell Spruill
-- 6/22/2011
-------------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------------
CREATE PROCEDURE usp_BackupDatabases
AS
BEGIN
-- construct a working table to hold all the databases from sys.databases
DECLARE @DBTable as 
TABLE
(
RowId int Identity(1,1),
DatabaseName varchar(150)
)

set nocount on

DECLARE @BackupRoot varchar(100)
DECLARE @DatabaseName as varchar(100)
DECLARE @RowId as int
DECLARE @RowCount as int
DECLARE @BackupPath varchar(500)
DECLARE @DateTime varchar(25)
DECLARE @InstanceName varchar(50)
DECLARE @DataPath varchar(100)
DECLARE @ProductVersion int
DECLARE @EngineEdition int
DECLARE @SQL as nvarchar(500)
DECLARE @R2 as bit
DECLARE @Body as nvarchar(max)
DECLARE @BackupType as nvarchar(5)
DECLARE @Start as datetime
DECLARE @End as int
DECLARE @Recipients as varchar(1000)
DECLARE @Profile_name as varchar(1000)
----------------------------------------------------------------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------------------------------------------------------------
----- Must be set based on individual needs
----------------------------------------------------------------------------------------------------------------------------------------------------
SET @BackupRoot = N'Q:'  -- everything is below this point.
SET @Recipients = 'sqldba@somecompany.com'
SET @Profile_name = 'SQL Backup Mail'
----------------------------------------------------------------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------------------------------------------------------------

SET @R2 = CASE  WHEN CHARINDEX(' R2 ', @@VERSION) > 0 then 1 else 0 end
SET @EngineEdition = CAST(SERVERPROPERTY('EngineEdition')  as int)
SET @ProductVersion = CAST( LEFT(CAST(SERVERPROPERTY('ProductVersion') as varchar),
CHARINDEX('.',CAST(SERVERPROPERTY('ProductVersion') as varchar)) -1) as int)
SET @DateTime=replace(replace(replace(convert(varchar(25), getdate(), 120),'-','_'),':','_'),' ','_')
SET @RowCount = (select COUNT(*) from @DBTable)
SET @InstanceName = ISNULL(CAST(SERVERPROPERTY('INSTANCENAME') as varchar),'Default')
SET @BackupType = 'Data'

-- Insert into the working table all the databases on this server
-- excluding databases like model, tempdb
insert into @DBTable(DatabaseName) 
SELECT  name FROM    sys.databases 
WHERE state = 0 -- online
AND name NOT IN (N'model', N'tempdb') -- exclude these databases
ORDER BY name -- by putting them in order we can track the backup progress on the file system.


-- select the top database in the table and start the backup
SELECT top 1 @RowId=RowId,@DatabaseName=DatabaseName from @DBTable
WHILE (@RowCount > 0)
BEGIN

-- data path = root + instancename + databasename
SET @DataPath=@BackupRoot + '\' + @InstanceName + '\' + @DatabaseName + '\' + @BackupType

-- backup path = datapath + databasename + time stamp
SET @BackupPath = @DataPath + '\' + @DatabaseName   + '_' +  @DateTime +'.Bak' 

-- if directory does not exist the create it
EXEC master.dbo.xp_create_subdir @DataPath

-- build sql statement
SET @SQL = 'BACKUP DATABASE [' + @DatabaseName + '] TO DISK = ''' + @BackupPath + ''' WITH INIT'
 
-- if SQL Server 2005 use this
IF (@ProductVersion >= 9 AND (@EngineEdition = 3 or @R2 = 1))
begin
SET @SQL = @SQL + ', FORMAT, CHECKSUM, STOP_ON_ERROR'
end

-- if SQL Server 2008 Enterprise edition or 2008 R2  and not encrypted then use compression 
IF (
@ProductVersion >= 10 AND 
(@EngineEdition = 3 or @R2 = 1) AND
NOT EXISTS  (Select 1 from sys.databases where name = @DatabaseName and is_encrypted = 1)
)
begin
SET @SQL = @SQL + ', COMPRESSION'
end

-- execute the sql statement
BEGIN TRY
EXECUTE sp_executeSQL @SQL
END TRY
BEGIN CATCH
SET @Body = '[Error Message]' + char(13) + char(10) + ERROR_MESSAGE()
+ char(13) + char(10) + char(13) + char(10) 
+ '[Database]' + char(13) + char(10) + @DatabaseName
+ char(13) + char(10) + char(13) + char(10) 
+ '[Backup Drive]'+ char(13) + char(10)  + @BackupRoot
+ char(13) + char(10) + char(13) + char(10) 
+ '[Instance Name]' + char(13) + char(10) + @InstanceName
+ char(13) + char(10) + char(13) + char(10) 
+ '[SQL Statement]'  + char(13) + char(10) + @SQL

EXEC msdb.dbo.sp_send_dbmail  
@importance='HIGH',
@profile_name=@Profile_name,
@recipients=@Recipients,
@subject=N'Database backup error',
@body=@Body
END CATCH

-- remove from working table
delete from @DBTable where RowId=@RowId

-- get next database to backup
SELECT top 1 @RowId=RowId,@DatabaseName=DatabaseName from @DBTable

-- decrement counter
Set @RowCount = @RowCount - 1
END

set nocount off
END

Rate

You rated this post out of 5. Change rating

Share

Share

Rate

You rated this post out of 5. Change rating