Technical Article

Restore DB from Disk File script

,

This script was designed to restore a backup of a production database from disk file, handle multiple DB files, move the files to new location, with new database name that is customized for the date of the backup, create any missing logins, and fix any user accounts that are orphaned by differing SIDs from the other server.
It has one area that is custom for my use, we create two user accounts and related roles, one is to allow 3rd party access (this reads minimal rights), and the other for internal application access (this reads full rights). These accounts are assigned to two roles. Which role defines how I create default passwords for new logins on my development server. You may notice that I like to make the login's default database tempdb, that way each time I restart the server, any objects created by the 3rd party login will be dumped when the tempdb is created.
Hey, works for me, especially for novice users.

-- RestoreDB script DAL - 4/22/2003
--
-- Search for %%% to find areas that need customization
--
USE master
GO

PRINT 'Restoring backup, Fixing Logins and User accounts at '+RTRIM(CONVERT(varchar(24),GETDATE(),121))+' '
PRINT ''
GO

DECLARE @BAK_file varchar(128)
, @DB_Path varchar(260)
, @DB_Name varchar(128)
, @Password varchar(10)
, @EPassword varchar(10)

-- %%% database name to restore to
SET @DB_Name = 't_DB'
-- %%% path for the backup file
SET @BAK_file = 'C:\Xfer\t_DB_20030404'
-- %%% default path for the new database files
SET @DB_Path = 'C:\Program Files\Microsoft SQL Server\MSSQL\data-- %%% default default password for a new login
SET @Password = 'password'
-- %%% default app password for a new login
SET @EPassword = '9@R_6X-A'

DECLARE @NewDB varchar(128)
, @LogicalName varchar(128)
, @PhysicalName varchar(260)
, @DatabaseName varchar(128)
, @Ext varchar(20)
, @MoDay varchar(4)
, @ExecStr nvarchar(4000)
, @LoginName varchar(20)
, @RoleName varchar(20)
, @Pass varchar(10)
, @Cnt int
, @Err int

SET NOCOUNT ON

CREATE TABLE #Media (
LogicalName varchar(128),
PhysicalName varchar(260), 
Type char(1),
FileGroupName varchar(128),
Size numeric(20,0),
MaxSize numeric(20,0) 
)

CREATE TABLE #Header (
BackupName varchar(128),
BackupDescription  varchar(255),
BackupType smallint,
ExpirationDate datetime,
Compressed tinyint,
Position smallint,
DeviceType tinyint,
UserName varchar(128),
ServerName varchar(128),
DatabaseName varchar(128),
DatabaseVersion  int,
DatabaseCreationDate  datetime, 
BackupSize numeric(20,0),
FirstLSN numeric(25,0),
LastLSN numeric(25,0),
CheckpointLSN  numeric(25,0),
DatabaseBackupLSN  numeric(25,0),
BackupStartDate  datetime,
BackupFinishDate  datetime,
SortOrder smallint,
CodePage smallint,
UnicodeLocaleId int,
UnicodeComparisonStyle int,
CompatibilityLevel  tinyint,
SoftwareVendorId  int,
SoftwareVersionMajor  int,
SoftwareVersionMinor  int,
SoftwareVersionBuild  int,
MachineName nvarchar(128),
Flags int,
BindingID uniqueidentifier,
RecoveryForkID uniqueidentifier,
Collation varchar(128)
)

SET @ExecStr = 'RESTORE HEADERONLY FROM DISK = '''+@BAK_file+''''
INSERT INTO #Header EXEC(@ExecStr)
SELECT @MoDay = REPLACE(CONVERT(varchar(5),BackupStartDate,1),'/',''), 
@DatabaseName = DatabaseName 
FROM #Header
DROP TABLE #Header
SET @NewDB = @DB_Name+'_'+@MoDay


SET @ExecStr = 'RESTORE FILELISTONLY FROM DISK = '''+@BAK_file+''''
INSERT INTO #Media EXEC(@ExecStr)

DECLARE MediaCursor CURSOR LOCAL FAST_FORWARD FOR 
SELECT LogicalName, PhysicalName 
FROM #Media
ORDER BY Type, LogicalName

OPEN MediaCursor
-- Get the 1st record
FETCH NEXT FROM MediaCursor INTO @LogicalName, @PhysicalName
SET @ExecStr = 'RESTORE DATABASE ['+@NewDB+'] FROM DISK = '''+@BAK_file+''' WITH '

-- Process the recordset
WHILE @@fetch_status = 0
BEGIN
SET @Ext = RIGHT(@PhysicalName,CHARINDEX('_',REVERSE(@PhysicalName)))
SET @ExecStr = @ExecStr + 'MOVE '''+@LogicalName+''' TO '''+@DB_Path+@NewDB+@Ext+''', '
FETCH NEXT FROM MediaCursor INTO @LogicalName, @PhysicalName
END
-- Clean up
CLOSE MediaCursor
DEALLOCATE MediaCursor
DROP TABLE #Media
SET @ExecStr = LEFT(RTRIM(@ExecStr),LEN(RTRIM(@ExecStr))-1)
PRINT 'Restoring database '''+@DatabaseName+''' from backup at '+RTRIM(CONVERT(varchar(24),GETDATE(),121))+' '
PRINT ''
EXEC(@ExecStr)
SELECT @Err = @@ERROR
IF @Err = 0
BEGIN
SET @ExecStr = 'BACKUP LOG ['+@NewDB+'] WITH TRUNCATE_ONLY'
EXEC(@ExecStr)
SET @ExecStr = 'ALTER DATABASE ['+@NewDB+'] SET RECOVERY SIMPLE'
EXEC(@ExecStr)
SET @ExecStr = 'DBCC SHRINKDATABASE (['+@NewDB+'], 20) WITH NO_INFOMSGS'
EXEC(@ExecStr)
PRINT ''
PRINT 'Finished Restoring database '''+@DatabaseName+''' from backup at '+RTRIM(CONVERT(varchar(24),GETDATE(),121))+' '
PRINT ''

CREATE TABLE #Users (LoginName varchar(128), RoleName varchar(128))
SET @ExecStr = 'SELECT u.name, r.name FROM '+@NewDB+'.dbo.sysusers  AS u '
SET @ExecStr = @ExecStr + 'INNER JOIN '+@NewDB+'.dbo.sysmembers AS m ON u.uid = m.memberuid '
SET @ExecStr = @ExecStr + 'INNER JOIN '+@NewDB+'.dbo.sysusers AS r ON m.groupuid = r.uid '
SET @ExecStr = @ExecStr + 'WHERE (u.issqluser <> 0 AND u.issqlrole = 0 AND u.gid <> 0) '
INSERT INTO #Users EXEC(@ExecStr)

-- Create the recordset for active users
DECLARE UserCursor CURSOR LOCAL FAST_FORWARD FOR 
SELECT LoginName, RoleName
FROM #Users
ORDER BY LoginName

OPEN UserCursor
-- Get the 1st record
FETCH NEXT FROM UserCursor INTO @LoginName, @RoleName
-- Process the recordset
IF @@FETCH_STATUS = 0
BEGIN
PRINT 'Fixing Logins and User accounts at '+RTRIM(CONVERT(varchar(24),GETDATE(),121))+' '
PRINT ''
END
WHILE @@FETCH_STATUS = 0
BEGIN
-- skip sa, dbo, guest
IF @LoginName NOT IN ('sa', 'dbo', 'guest')
BEGIN
PRINT char(9) + 'Login: ''' + @LoginName + ''' Role: ''' + @RoleName + ''''
IF @RoleName = 'AppDefault'
SET @Pass = @Password
ELSE
SET @Pass = @EPassword
        -- Process the User account
-- See if the Login exists
IF NOT EXISTS (SELECT loginname FROM master.dbo.syslogins WHERE loginname = @LoginName)
BEGIN
-- Create the Login, using the default password
EXEC sp_addlogin @LoginName, @Pass, 'tempdb'
PRINT char(9) + char(9) + 'Created Login for ' + @LoginName
END
ELSE
IF EXISTS(SELECT loginname FROM master.dbo.syslogins WHERE isntname=0 AND password IS NULL AND loginname = @LoginName)
BEGIN
-- Change the Login password from Null
EXEC sp_password NULL, @Pass, @LoginName
PRINT char(9) + char(9) + 'Changed password for Login ' + @LoginName
END
-- See if the User account is orphaned
SET @ExecStr = 'SELECT @Rows = COUNT(sysusers.name) FROM '+@NewDB+'.dbo.sysusers AS sysusers LEFT JOIN master.dbo.syslogins AS syslogins ON sysusers.sid = syslogins.sid WHERE syslogins.sid IS NULL AND sysusers.name = '''+@LoginName+''' '
EXEC sp_executesql @ExecStr, N'@Rows int out', @Cnt out
IF @Cnt > 0
BEGIN
SET @ExecStr = @NewDB+'.dbo.sp_change_users_login ''Auto_Fix'', '''+@LoginName+''' '
EXEC(@ExecStr)
PRINT char(9) + char(9) + 'Fixed User account for ' + @LoginName
END
-- Test again to fix for 'duplicate SID'
SET @ExecStr = 'SELECT @Rows = COUNT(sysusers.name) FROM '+@NewDB+'.dbo.sysusers AS sysusers LEFT JOIN master.dbo.syslogins AS syslogins ON sysusers.sid = syslogins.sid WHERE syslogins.sid IS NULL AND sysusers.name = '''+@LoginName+''' '
EXEC sp_executesql @ExecStr, N'@Rows int out', @Cnt out
IF @Cnt > 0
BEGIN
SET @ExecStr = @NewDB+'.dbo.sp_dropuser '''+@LoginName+''' '
EXEC(@ExecStr)
PRINT char(9) + char(9) + 'Deleted User account for ' + @LoginName
SET @ExecStr = @NewDB+'.dbo.sp_adduser '''+@LoginName+''', '''+@LoginName+''', '''+@RoleName+''' '
EXEC(@ExecStr)
PRINT char(9) + char(9) + 'Created User account for ' + @LoginName
END
END -- @LoginName NOT IN ('sa', 'dbo', 'guest')
FETCH NEXT FROM UserCursor INTO @LoginName, @RoleName
END --WHILE @@FETCH_STATUS = 0
-- Clean up
CLOSE UserCursor
DEALLOCATE UserCursor
DROP TABLE #Users
END -- @Err = 0
SET NOCOUNT OFF 

PRINT ''
PRINT 'Finished Restoring backup, Fixing Logins and User accounts at '+RTRIM(CONVERT(varchar(24),GETDATE(),121))+' '
GO

Rate

Share

Share

Rate