The amazing adventures of Doug Hughes

Continuing on my SQL search script posted yesterday, I am posting two stored procedures for backing up and restoring Microsoft SQL databases easily.

I use the backup script frequently when publishing or making large changes to databases. Obviously, this script should really be used in addition to a scheduled maintenance and backup plan and is not intended to replace that.

Another thing to keep in mind is that these two procedures just abstract calling the built in backup and restore commands. I think this syntax is easier to remember and the hard coded options are right for what I tend to do. Feel free to tweak them as needed. I tend to create these procedures in my master database.

Here’s the SQL for BackupDatabase.

CREATE PROCEDURE BackupDatabase
	@database varchar(100),
	@backupDir varchar(500)
AS

IF RIGHT(@backupDir, 1) = ''
	SET @backupDir = @backupDir + @database + '.bak'
ELSE
	SET @backupDir = @backupDir + '' + @database + '.bak'

BACKUP DATABASE @database
TO DISK = @backupDir
WITH STATS = 10

The BackupDatabase procedure accepts to parameters, the name of the database to backup and the path to the directory where the backup file will be written. The following is an example of how to call the procedure.

master..BackupDatabase 'Northwind', 'd:temp'

This example will backup the Northwind database to the d:temp directory, creating a file named Northwind.bak. One thing I might suggest doing is altering the procedure to append the current date to the end of the file name.

The RestoreDatabase procedure depends on a helper procedure which returns the files which are contained within a backup file. You can call this procedure directly, but there’s really not much point to this. Execute the following SQL to create the procedure.

CREATE PROCEDURE GetBackupFileList @backupFile varchar(500)
AS
RESTORE FILELISTONLY FROM DISK = @backupFile

Once you have created the GetBackupFileList procedure the RestoreDatabase procedure can be created by executing this SQL code:

CREATE PROCEDURE RestoreDatabase @backupFile varchar(500),
@newDatabaseName varchar(100)
AS
-- // create a temp table to hold the file list for the db
CREATE TABLE #fileList (
	LogicalName nvarchar(128),
	PhysicalName nvarchar(260),
	Type char(1),
	FileGroupName nvarchar(128),
	Size numeric(20,0),
	MaxSize numeric(20,0)
)

-- // Declare a variable to hold the restore statement
DECLARE @RestoreStmt varchar(500)

-- // start the restore stmnt
SET @RestoreStmt = '
RESTORE DATABASE ' + @newDatabaseName + '
FROM DISK = '' + @backupFile + ''
WITH
'
INSERT #fileList
EXECUTE GetBackupFileList @backupFile

--- // declare some vars to hold the filenames and types
DECLARE @LogicalName nvarchar(128)
DECLARE @PhysicalName nvarchar(260)
DECLARE @Type char(1)
DECLARE @LastSlash int

DECLARE fileListCsr CURSOR FOR
	SELECT LogicalName, PhysicalName, Type
	FROM #fileList
	OPEN fileListCsr

	FETCH NEXT FROM fileListCsr INTO @LogicalName, @PhysicalName, @Type
	WHILE @@FETCH_STATUS = 0
	BEGIN
	-- // get the path from @PhysicalName
	SET @LastSlash = CHARINDEX('', REVERSE(@PhysicalName))
	SET @PhysicalName = LEFT(@PhysicalName, LEN(@PhysicalName) - @LastSlash) + ''

	-- // check the type of this file
	IF @Type = 'D'
		SET @PhysicalName = @PhysicalName + @newDatabaseName + '_data.mdf'
	ELSE
		SET @PhysicalName = @PhysicalName + @newDatabaseName + '_log.ldf'

	-- // update the file paths
	SET @RestoreStmt = @RestoreStmt + '
	MOVE '' + @LogicalName + '' TO '' + @PhysicalName + '',
	'
	FETCH NEXT FROM fileListCsr INTO @LogicalName, @PhysicalName, @Type
END

-- // add stats
SET @RestoreStmt = @RestoreStmt + ' STATS = 10'
PRINT @RestoreStmt
CLOSE fileListCsr
DROP TABLE #fileList

-- // execute the restore stmnt
EXEC( @RestoreStmt )

This RestoreDatabase procedure accepts two parameters, the path to the backup file and the name of the database to restore. The following is an example which restores the backup file we created earlier to a database named NewNorthwind.

master..RestoreDatabase 'd:tempNorthwind.bak', 'NewNorthwind'

I’ve found these two procedures to be very useful over the years, I hope you do too.

Please let me know if you have any feedback.

Comments on: "MS SQL Backup and Restore Procedures" (14)

  1. I’m in a corporate setting where I don’t have backup/restore rights on my database (where I do have create table, etc.). Will this script bypass the SA requirements and let me backup?

    Like

  2. Doug Hughes said:

    I would expect not. One thing you could try is just running the following command in QA. If it so, at least the backup procedure will work.

    BACKUP DATABASE ‘Northwind’
    TO DISK = ‘d:tempnorthwind.bak’
    WITH STATS = 10

    Why not ask for permissions? It seems important to me.

    Like

  3. Manjunath said:

    GetBackupFileList procedure is missing could u please comment on this

    Like

  4. Manjunath said:

    GetBackupFileList procedure is missing could u please comment on this

    Like

  5. Get following error when running restore (sql 2005). Any ideas?
    Msg 213, Level 16, State 7, Procedure GetBackupFileList, Line 5
    Insert Error: Column name or number of supplied values does not match table definition.
    Msg 3013, Level 16, State 1, Procedure GetBackupFileList, Line 5
    RESTORE FILELIST is terminating abnormally.

    Like

  6. Aron Kansa said:

    If you have a web app where you need to create new databases from a template database “on the fly”, this would be a great way, right?

    Just make the backup .bak file once, then in the code behind call just the restore Stored Proc and pass it the desired new db name.

    let me know if this isn’t the best solution, cheers!

    Like

  7. Doug Hughes said:

    Aron – I’m not sure I’d do it this way or not. I’d probably look at scripting the database first. On the other hand, simply having a backup does seem to be somewhat easier to mantain.

    Like

  8. APatel, I’m receiving the same error. I tried adding “WITH REPLACE” to the code, but still seem to get the same error. Have you found a solution to the problem?

    Like

  9. alter PROCEDURE sp_RestoreDB
    @backupFile varchar(500),
    @newDatabaseName varchar(100)
    AS

    — // create a temp table to hold the file list for the db
    CREATE TABLE #fileList ( LogicalName nvarchar(128),
    PhysicalName nvarchar(260),
    Type char(1),
    FileGroupName nvarchar(128),
    Size numeric(20,0),
    MaxSize numeric(20,0),
    FileID bigint,
    CreateLSN numeric(25,0),
    DropLSN numeric(25,0) NULL,
    UniqueID uniqueidentifier,
    ReadOnlyLSN numeric(25,0) NULL,
    ReadWriteLSN numeric(25,0) NULL,
    BackupSizeInBytes bigint,
    SourceBlockSize int,
    FileGroupID int,
    LogGroupGUID uniqueidentifier NULL,
    DifferentialBaseLSN numeric(25,0) NULL,
    DifferentialBaseGUID uniqueidentifier,
    IsReadOnly bit,
    IsPresent bit )
    — // Declare a variable to hold the restore statement
    DECLARE @RestoreStmt varchar(500)
    — // start the restore stmnt
    SET @RestoreStmt = ‘
    RESTORE DATABASE ‘ + @newDatabaseName + ‘
    FROM DISK = ” + @backupFile + ”
    WITH

    INSERT #fileList
    EXECUTE GetBackupFileList @backupFile

    — // declare some vars to hold the filenames and types
    DECLARE @LogicalName nvarchar(128)
    DECLARE @PhysicalName nvarchar(260)
    DECLARE @Type char(1)
    DECLARE @LastSlash int

    DECLARE fileListCsr CURSOR FOR
    SELECT LogicalName, PhysicalName, Type
    FROM #fileList

    OPEN fileListCsr
    FETCH NEXT FROM fileListCsr INTO @LogicalName, @PhysicalName, @Type
    WHILE @@FETCH_STATUS = 0
    BEGIN
    — // get the path from @PhysicalName
    SET @LastSlash = CHARINDEX(”, REVERSE(@PhysicalName))
    SET @PhysicalName = LEFT(@PhysicalName, LEN(@PhysicalName) – @LastSlash) + ”

    — // check the type of this file
    IF @Type = ‘D’
    SET @PhysicalName = @PhysicalName + @newDatabaseName + ‘_data.mdf’
    ELSE
    SET @PhysicalName = @PhysicalName + @newDatabaseName + ‘_log.ldf’

    — // update the file paths
    SET @RestoreStmt = @RestoreStmt + ‘
    MOVE ” + @LogicalName + ” TO ” + @PhysicalName + ”,

    FETCH NEXT FROM fileListCsr INTO @LogicalName, @PhysicalName, @Type
    END

    — // add stats
    SET @RestoreStmt = @RestoreStmt + ‘ STATS = 10’

    PRINT @RestoreStmt

    CLOSE fileListCsr

    DROP TABLE #fileList

    Like

  10. Richard Usigan said:

    Your codes is so cool

    its awsome bro

    your codes is best I sureness used those kind of codes…

    yahooooooOOOOoooOOOoo!!!!!
    thanks

    Like

  11. Can’t see, to get it to work …

    Had to change this…

    CREATE TABLE #fileList ( LogicalName nvarchar(128),
    PhysicalName nvarchar(260),
    Type char(1),
    FileGroupName nvarchar(128),
    Size numeric(20,0),
    MaxSize numeric(20,0),
    Field numeric(20,0),
    –FileID bigint,
    CreateLSN numeric(25,0),
    DropLSN numeric(25,0) NULL,
    UniqueID uniqueidentifier,
    ReadOnlyLSN numeric(25,0) NULL,
    ReadWriteLSN numeric(25,0) NULL,
    BackupSizeInBytes bigint,
    SourceBlockSize int,
    FileGroupId int,
    LogGroupGUID uniqueidentifier NULL,
    DifferentialBaseLSN numeric(25,0) NULL,
    DifferentialBaseGUID uniqueidentifier,
    IsReadOnly bit,
    IsPresent bit,
    TDEThumbprint varchar(MAX) )

    Still nothing worked ???
    Does the database need to exists where it restores it to ?

    I’m lost…

    Like

  12. Richard Douglas said:

    In answer to Ryan’s question no a stored procedure would not allow you to bypass the security rights you require to backup or restore a database in SQL 2000.

    However in SQL 2005 a new piece of functionality wass introduced where you can let code run under the permisions of another user. This utilises the “EXECUTE AS” clause. If this were added to the start of the procedures under the pretext of running under a user with those specified rights (db_BackUPOperator) you would be able to perform the task without having the explicit permissions. You would need execute permissions on the stored procedures of course.

    Rich

    Like

  13. Hi,

    I created these (backup, restore) stored procs and backup is working fine but restore is failed with next error message:

    Server: Msg 3201, Level 16, State 2, Line 2
    Cannot open backup device ‘e:dataMSSQLBACKUP + @backupFile + ‘. Device error or device off-line. See the SQL Server error log for more details.
    Server: Msg 3013, Level 16, State 1, Line 2
    RESTORE DATABASE is terminating abnormally.

    The command was:
    EXEC RestoreDatabase ‘E:PharmaTrendPHARMANOVA_200911121128.bak’, ‘PHARMANOVA’

    So I had backup my DB E:PharmaTrend folder and restore procedure tried to restore it from default MsSQL backup folder!!! Why?

    Thx in advance for your help!
    Wic

    Like

  14. Shemeer NS Mumbai said:

    I resolved the issue…..

    This RestoreProc will overwrite the db if it exists….
    will restore the first file if the bak file contains more than one backup

    ALTER PROCEDURE RestoreDatabase
    @backupFile varchar(500),
    @newDatabaseName varchar(100)
    AS

    — // create a temp table to hold the file list for the db
    CREATE TABLE #fileList ( LogicalName nvarchar(128),
    PhysicalName nvarchar(260),
    Type char(1),
    FileGroupName nvarchar(128),
    Size numeric(20,0),
    MaxSize numeric(20,0),
    FileID bigint,
    CreateLSN numeric(25,0),
    DropLSN numeric(25,0) NULL,
    UniqueID uniqueidentifier,
    ReadOnlyLSN numeric(25,0) NULL,
    ReadWriteLSN numeric(25,0) NULL,
    BackupSizeInBytes bigint,
    SourceBlockSize int,
    FileGroupID int,
    LogGroupGUID uniqueidentifier NULL,
    DifferentialBaseLSN numeric(25,0) NULL,
    DifferentialBaseGUID uniqueidentifier,
    IsReadOnly bit,
    IsPresent bit )

    — // Declare a variable to hold the restore statement
    DECLARE @RestoreStmt varchar(500)
    — // start the restore stmnt
    SET @RestoreStmt = ‘
    RESTORE DATABASE ‘ + @newDatabaseName + ‘
    FROM DISK = ”’ + @backupFile + ”’
    WITH FILE = 1,

    INSERT #fileList
    EXECUTE GetBackupFileList @backupFile

    — // declare some vars to hold the filenames and types
    DECLARE @LogicalName nvarchar(128)
    DECLARE @PhysicalName nvarchar(260)
    DECLARE @Type char(1)
    DECLARE @LastSlash int

    DECLARE fileListCsr CURSOR FOR
    SELECT LogicalName, PhysicalName, Type
    FROM #fileList

    OPEN fileListCsr
    FETCH NEXT FROM fileListCsr INTO @LogicalName, @PhysicalName, @Type
    WHILE @@FETCH_STATUS = 0
    BEGIN
    — // get the path from @PhysicalName
    SET @LastSlash = CHARINDEX(”, REVERSE(@PhysicalName))
    SET @PhysicalName = LEFT(@PhysicalName, LEN(@PhysicalName) – @LastSlash) + ”

    — // check the type of this file
    IF @Type = ‘D’
    SET @PhysicalName = @PhysicalName + @newDatabaseName + ‘_data.mdf’
    ELSE
    SET @PhysicalName = @PhysicalName + @newDatabaseName + ‘_log.ldf’

    — // update the file paths
    SET @RestoreStmt = @RestoreStmt + ‘
    MOVE ”’ + @LogicalName + ”’ TO ”’ + @PhysicalName + ”’,

    FETCH NEXT FROM fileListCsr INTO @LogicalName, @PhysicalName, @Type
    END

    — // add stats
    SET @RestoreStmt = @RestoreStmt + ‘ STATS = 10,REPLACE’

    PRINT @RestoreStmt

    CLOSE fileListCsr

    DROP TABLE #fileList

    — // execute the restore stmnt
    EXEC( @RestoreStmt )

    Shemeer NS
    Technology Specialist
    Mumbai

    Like

Comments are closed.

Tag Cloud