Tara Kizer Blog

Tara Kizer

RESTORE stored procedure

The below stored procedure performs a RESTORE of the newest BAK file in the specified directory (@bkpDir).  I recommend putting it into an Admin database (hey just name it Admin!) rather than in master. 

----------------------------------------------------------------------------------------------------
-- OBJECT NAME         : isp_Restore
-- AUTHOR                    : Tara Duggan
-- DATE                          : November 3, 2005
-- INPUTS                      : @dbName - name to use for the restored database
--                                       @bkpDir - full path to the directory where the BAK files exist
--                                       @newDataLocation - new location and file name for the MDF, can be NULL
--                                       @newLogLocation - new location and file name for the LDF, can be NULL
-- OUTPUTS                    : None
-- RETURN CODES        : 0 - success
--                                        1 - invalid path
--                                        2 - no BAK files exist in @bkpDir
--                                        3 - backup contains more than 2 D files which isn't supported by this sproc
--                                        4 - restore error
-- DEPENDENCIES        : None
-- DESCRIPTION            : This stored procedure performs a restore of the newest BAK file in a specified directory.
-- EXAMPLES (optional)  :
/*
  DECLARE @rc tinyint
  EXEC @rc = dbo.isp_Restore @dbName = 'Db1', @bkpDir = 'H:\MSSQL\BACKUP\Db1', @newDataLocation = 'F:\MSSQL\DATA\Db1_Data.MDF', @newLogLocation = 'G:\MSSQL\DATA\Db1_Log.LDF'
  PRINT @rc
*/
----------------------------------------------------------------------------------------------------
CREATE  PROC dbo.isp_Restore
(@dbName sysname, @bkpDir nvarchar(1000), @newDataLocation nvarchar(1000), @newLogLocation nvarchar(1000))
AS

SET NOCOUNT ON

DECLARE @cmd sysname, @bkpFile nvarchar(1000), @sql nvarchar(4000), @logicalDataName nvarchar(128), @logicalLogName nvarchar(128)

-- Add a backslash to the end of the path if one doesn't exist
IF REVERSE(SUBSTRING(@bkpDir, 1, 1)) <> '\'
 SET @bkpDir = @bkpDir + '\'

-- Get files sorted by date
SET @cmd = 'dir ' + @bkpDir + '*.BAK /OD'

CREATE TABLE #Dir(DirInfo VARCHAR(7000)) -- Stores the dir results
CREATE TABLE #BackupFiles(BackupDate varchar(10), BackupFileName nvarchar(1000)) -- Stores only the data we want from the dir

INSERT INTO #Dir
EXEC master.dbo.xp_cmdshell @cmd

IF EXISTS (SELECT * FROM #Dir WHERE DirInfo = 'The system cannot find the path specified.')
 RETURN 1

INSERT INTO #BackupFiles
SELECT SUBSTRING(DirInfo, 1, 10), SUBSTRING(DirInfo, LEN(DirInfo) -  PATINDEX('% %', REVERSE(DirInfo)) + 2, LEN(DirInfo))
FROM #Dir
WHERE ISDATE(SUBSTRING(DirInfo, 1, 10)) = 1 AND DirInfo NOT LIKE '%<DIR>%'

IF @@ROWCOUNT = 0
 RETURN 2

-- Get the newest file
SELECT TOP 1 @bkpFile = BackupFileName
FROM #BackupFiles
ORDER BY BackupDate DESC

DROP TABLE #Dir, #BackupFiles

SET @cmd = @bkpDir + @bkpFile

-- Stores RESTORE FILELISTONLY result set
CREATE TABLE #RestoreFileListOnly
(
 LogicalName nvarchar(128),
 PhysicalName nvarchar(260),
 Type char(1),
 FileGroupName nvarchar(128),
 [Size] numeric(20,0),
 [MaxSize] numeric(20,0)
)

INSERT INTO #RestoreFileListOnly
EXEC('RESTORE FILELISTONLY FROM DISK = ''' + @cmd + '''')

IF @@ROWCOUNT <> 2
 RETURN 3

SELECT @logicalDataName = LogicalName
FROM #RestoreFileListOnly
WHERE Type = 'D'

SELECT @logicalLogName = LogicalName
FROM #RestoreFileListOnly
WHERE Type = 'L'

DROP TABLE #RestoreFileListOnly

SET @sql = ''
SET @sql = @sql + 'RESTORE DATABASE ' + @dbName + CHAR(10)
SET @sql = @sql + 'FROM DISK = ''' + @cmd + '''' + CHAR(10)
SET @sql = @sql + 'WITH' + CHAR(10)
SET @sql = @sql + CHAR(9) + 'REPLACE'

IF @newDataLocation IS NOT NULL
BEGIN
 SET @sql = @sql + ',' + CHAR(10)
 SET @sql = @sql + CHAR(9) + 'MOVE ''' + @logicalDataName + ''' TO ''' + @newDataLocation + ''''
END

IF @newLogLocation IS NOT NULL
BEGIN
 SET @sql = @sql + ',' + CHAR(10)
 SET @sql = @sql + CHAR(9) + 'MOVE ''' + @logicalLogName + ''' TO ''' + @newLogLocation + ''''
END

PRINT @sql
EXEC(@sql)

IF @@ERROR <> 0
 RETURN 4
ELSE
 RETURN 0

GO

If you don't use BAK as the extension for your backups or perhaps you are restoring transaction logs instead, then just change the line directly below the comment “Get files sorted by date“ to whatever meets your requirements.

Legacy Comments


Brett
2005-11-09
re: RESTORE stored procedure
Return Codes?

tsk, tsk....

Thanks though for the code.....


Tara
2005-11-09
re: RESTORE stored procedure
So you use output parameters? How do you exit the stored procedure, with labels/gotos? I don't think output parameters are appropriate here as I am indicating a problem, just like a return code. But really, either way you go, it's only a preference thing and not a rule. MS even chimed in on this when Kristen asked Paul to see what their opinion was.

Clint
2006-01-05
re: RESTORE stored procedure
Good code! I've been wanting ideas on dragging info out of xp_cmdshell and filelist commands.

disclaimer - I have not spent a lot of time digging yet....
but it *seems* SQL 2005 backup files have added more columns into the FileList. So the current temp table as you have it did not work.
I've not yet dug into the properties to add those new columns.

Tara
2006-01-05
re: RESTORE stored procedure
Once I start using 2005 for purposes other than getting up to speed on the product, I'll be testing and updating all of the maintenance routines that I've blogged. Stay tuned!

Paul
2006-01-13
re: RESTORE stored procedure
Nice code - the collection of the BackupFileName could be simplified by using

SET @cmd = 'dir ' + @bkpDir + '*.BAK /OD/B'

but maybe that's just being picky :)

Matthew Martin
2006-05-04
re: RESTORE stored procedure
What is the license on your fantastic scripts? (for example, I've extended some of your scripts some and wanted to publish them to my blog)

Tara
2006-05-04
re: RESTORE stored procedure
Feel free to post it just make sure to reference where you got the original code from.

Andy
2006-05-31
re: RESTORE stored procedure
Hi

The code looks brilliant but I keep getting a return code of 1 in SQL Express and can't work out what's wrong - the command completes successfully but the database is not restored.

Tara
2006-05-31
re: RESTORE stored procedure
I would suggest looking at the statement returned by the PRINT @sql line to see if it is a valid RESTORE command.

Marcio
2006-11-30
re: RESTORE stored procedure
I try use with vb.net but something is wrong i cant find.

no one exception but dont work see how i pass parameter...

And if i use sql console ( EXEC srv_Restore @dbName = 'msdb', @bkpDir = 'c:\MSSQL\BACKUP\MSDB', @newDataLocation = null , @newLogLocation = null ) this go

all parametrs the same up

Thanks

miComando.CommandType = CommandType.StoredProcedure
miComando.Parameters.Add("@dbName", OleDbType.VarChar, 100).Value = dbName
miComando.Parameters.Add("@bkpDir", OleDbType.VarChar, 100).Value = (carpeta & "\")
miComando.Parameters.Add("@newDataLocation", OleDbType.Empty).Value = newDataLocation
miComando.Parameters.Add("@newLogLocation", OleDbType.Empty).Value = newLogLocation