Av rating:
Total votes: 16
Total comments: 16


Pop Rivett
Pop Rivett's SQL Server FAQ No.4: Pop does Log Shipping
30 October 2006

Pop Rivett engages in Log Shipping

A lot of people come up to me and say, "Pop, you've been around a bit, how do you ensure that your standby SQL Server is always in synch with your production one?" Usually I sigh wearily and tell them that it takes a lifetimes experience and a natural flair for the task, and would take far too long to explain, but this once I've decided to share with you a technique that I've always found effective.

It's based around log shipping – a pretty standard technique for keeping two databases synchronised. In essence, one keeps a spare copy of a production database in 'standby' mode, so it can be switched in reasonably quickly if the primary database fails.

Figure 1: Pop attempting to ship an entire tree structure

The first thing to do is ensure that your "live" database is using the 'full recovery' model. Next, one creates a 'standby' clone by restoring a full backup and then applying all subsequent incremental logs to it, in sequence. The two databases, at that point of time, should be identical. (You can always check this with SQL Compare and SQL Data Compare).

Logs are then restored in sequence to the 'standby' as they are backed up from the primary server. This means that all transactions performed by the primary server will then be performed on the standby, thereby keeping the two synchronised. If the primary server fails, the standby server can then be brought into operation, though this process is, of necessity, a manual one.

Process

The process, as demonstrated here, comprises the following three basic steps:

  1. On the primary server (svr1) a backup job is scheduled for the database(s) in question, using the backup procedure, s_BackupAllDatabases, previously described in Pop Rivett Backs Up.
  2. On the Standby server, a procedure, s_nrSyncDir, copies across from the primary server the latest Full backup, and/or any new Log backups
  3. On the Standby server, the database(s) in question is restored using the stored procedure, s_RestoreDatabase, previously described in Pop Rivett Restores. It will restore the Full backup followed by the logs.

NOTE:
All of the scripts required to try out this log shipping process are provided in the code download for this article (see the "Code Download" link in the box to the right of the article title).

The 'Backup' and 'Restore' stored procedures use the following convention for the format of the backup file names so as to ensure that the right files are used in the correct sequence:

  • Databasename_Full_yyyymmdd_hhmmss.bak for a full backup
  • Databasename _Log_yyyymmdd_hhmmss.bak for an incremental backup

Let's step through this process in full detail.

On the Primary server…

1. Create a database called "Admin"

2. In the Admin database, create the DatabaseBackup table

USE Admin
CREATE TABLE DatabaseBackup
(
  Name VARCHAR(128) PRIMARY KEY NONCLUSTERED ,
  BackupFlagFull VARCHAR(1) NOT NULL CHECK (BackupFlagFull IN ('Y','N')) ,
  BackupFlagLog VARCHAR(1) NOT NULL CHECK (BackupFlagLog IN ('Y','N')) ,
  RetentionPeriodFull datetime NOT NULL ,
  RetentionPeriodLog datetime NOT NULL
)

You can use this table to control which databases should be backed up and to set the retention period of the backup files.

3. Create the stored procedure Admin..s_BackupAllDatabases

4. Create the folders:

  • C:\Backup\Full\
  • C:\Backup\Log\

5. Create jobs to backup the database

a. Full backup scheduled daily:

s_BackupAllDatabases 'C:\Backup\Full\', 'Full'

b. Log backup scheduled every 15 mins:

   s_BackupAllDatabases 'C:\Backup\Log\', 'Log'

---Editor's Notes---
xp_cmdshell needs to be enabled on both the primary and standby servers. During my testing I simply enabled it using the SQL Server Surface Area configuration tool, (under Surface Area Configuration for Features), ran the examples then disabled it again manually. Generally, however, you would assign the right to the scheduler user to enable it, run the job, and then disable it. One can specify the user with which one runs the task from Enterprise manager /SSMS (Edit job step | advanced tab | Run as user), after creating a user with the necessary rights.

On another note – look out for those trailing "\" on the paths in step 5. If you miss them out (as I did the first time) the procedure will appear to "work" but the .bak files will have the wrong names.
---End Editor's Notes---

On the Standby server…

1. Create the folders:

  • C:\BackupCopy\Full\
  • C:\BackupCopy\Log\
  • C:\BackupCopy\Log\Archive\
  • C:\sql\Data\
  • C:\sql\Log\

2. Synchronise the SQL Server login IDs between the primary and standby servers, either by scripting the login IDs from the primary server and then running the script on the standby server to create the login Ids. This is easier with Login IDs that use NT authentication. Alternatively, if your standby server is being used for nothing else, then back up the Master database on the primary server and restore it to the standby.

3. Create a database called Admin

4. In the Admin database, create the following stored procedures:

  • s_nrSyncDir
  • s_RestoreDatabase

5. Create a job to copy all backups from the source server. Schedule it every 5 mins or however often synchronisation should be set. E.g.

EXEC s_nrSyncDir 
       @LocalDir1 = 'c:\BackupCopy\Full\' ,
       @LocalDir2 = NULL ,
       @RemoteDir = '\\svr1\c$\Backup\Full\' ,
       @FileMask = '*.bak' ,
       @RetainPeriod = '19000105'



EXEC s_nrSyncDir
       @LocalDir1 = 'c:\BackupCopy\Log\' ,
       @LocalDir2 = 'c:\BackupCopy\Log\Archive\' ,
       @RemoteDir = '\\svr1\c$\Backup\Log\' ,
       @FileMask = '*.bak' ,
       @RetainPeriod = '19000105'


/*This will copy all files more recent than @RetainPeriod (5 days)
from @RemoteDir to @LocalDir1 that are not found in
@LocalDir1 or @LocalDir2 */

6. Copy the latest full backup of the database from c:\BackupCopy\Full\ to c:\BackupCopy\Log\

7. Schedule the following job to run - or add it as a second task to the job above. I would suggest creating a separate job for copying the full backups and add this to the log file copy.

EXEC s_RestoreDatabase
   @SourcePath = 'c:\BackupCopy\Log\' ,
   @archivePath = 'c:\BackupCopy\Log\Archive\' ,
   @DataPath = 'c:\sql\data\' ,
   @LogPath = 'c:\sql\log\' ,
   @recover = 'norecovery' ,
   @recipients = '' ,
   @Database = 'mydb' 

This will now drop the database mydb if it exists, restore the full backup (moving the data and log files to the requested directories) and restore all the logs. Note the following:

  • The database will "recovering" and ready to apply further logs. It will be inaccessible ("restoring" will appear after its name). If you execute a RESTORE DATABASE command it should bring it on-line. If you do this, however, you will have to restore another full database (which will drop the database and recreate it) before you can restore more logs. Alternatively, you can restore to standby which will enable you to access the database in read only mode – you will have to specify the rollback file to restore further logs.
  • Any logs timestamped before the full backup are moved to c:\BackupCopy\Log\Archive\ before the full database restore.
  • After each file is restored it is moved to c:\BackupCopy\Log\Archive\. Hence the requirement for two local folders in s_nrSyncDir.

---Editor's Notes---
In the @RemoteDir assignment in step 5, C$ refers to an admin share. I did not have permission to access this, so I simply created a share called Backup on the C:\Backup folder on the primary server (by right-clicking Shares in the Computer Management Windows admin tool, and selecting Create New Share to start the wizard). So the assignment, for me, was: @RemoteDir = '\\svr1\Backup\Full\'. You might need the fully-qualified path for svr1 (e.g. <servername>.<domainname>.com).

Just for testing purposes I gave access permissions on this folder to Everyone. Of course, in general you would merely grant the necessary permissions to the process running the nrSyncDir procedure.

The definition of the #Files temporary table, defined in s_RestoreDatabase, works for SQL Server 2000 but that definition has changed in SQL Server 2005. If you are running SQL 2005, you will need to replace the definition of that table in the s_RestoreDatabase.sql script with the one provided in Files.sql
---End Editor's Notes---

If the log shipping breaks down, because of a corrupt log file or someone has interfered with the source database, then it must be restarted as follows:

  1. Stop the restore job.
  2. Copy the latest full backup into c:\BackupCopy\Log\.
  3. Recover the database (restore database mydb with recovery) - this should really be included in the restore procedure.
  4. Restart the restore job.

Figure 2: Pop Rivett well on the way to success



This article has been viewed 24215 times.
Pop Rivett

Author profile: Pop Rivett

Pop spent his formative years working in assembler on IBM Series/1 but retrained in VB when that went out of fashion. He soon realised how little relational database expertise existed in most companies and so started to spend most of his time working on that. He now sticks to architecture, release control / IT processes, SQL Server, DTS, SSIS, and access methods in VB/ASP/.NET/Crystal Reports/reporting services. He has been involved with SQL Server since the old days of v4.2 to v2005. He tries to stay away from anything presentation oriented (see www.mindsdoor.net). Theoretically he is semi-retired but seems to keep being offered potentially interesting work.

Search for other articles by Pop Rivett

Rate this article:   Avg rating: from a total of 16 votes.


Poor

OK

Good

Great

Must read
 
Have Your Say
Do you have an opinion on this article? Then add your comment below:
You must be logged in to post to this forum

Click here to log in.


Subject: VARCHAR?
Posted by: IDisposable (view profile)
Posted on: Tuesday, October 31, 2006 at 11:50 AM
Message: Why are the flags VARCHAR(1) instead of CHAR(1) in the DatabaseBackup table?

BTW, cool and thanks...

Subject: Nice - but a bit pointless?
Posted by: BostonBrian (view profile)
Posted on: Thursday, November 02, 2006 at 7:45 AM
Message: Article seems to be detailed, but there are tools out there that let you set up log shipping without any of this hassle. Why not use something like SQL Backup or Litespeed?

Subject: Re: Nice - but a bit pointless?
Posted by: Phil Factor (view profile)
Posted on: Friday, November 03, 2006 at 5:34 AM
Message: Cost.
Also, without Pop Rivett's help, one could easily go around thinking that Log Shipping was complicated and for the boffins only. I give thanks to the old fellow.

Subject: re: Nice - but a bit pointless
Posted by: nigelrivett (view profile)
Posted on: Friday, November 03, 2006 at 6:31 AM
Message: >> Why not use something like SQL Backup or Litespeed?
You could ask
why not use the log shipping installed with sql server?

Why would you?
It is so simple to set up yourself why not do it. Then you know what's going on and more importantly what has happened and how to correct it if there is a problem.

I see it in the same category as using a backup statement to do a backup rather than a maintenance plan.

Subject: re: VARCHAR?
Posted by: nigelrivett (view profile)
Posted on: Friday, November 03, 2006 at 6:38 AM
Message: >> Why are the flags VARCHAR(1) instead of CHAR(1) in the DatabaseBackup table?

ummm, errr, tricky question, ....

Probably because my fingers type varchar without help so I don't use char unless it would be useful. In this case storage and performance isn't an issue.
Same as I will use int for most things due to the time saved in checking datatypes or thinking about what it should really be.

That only applies for small tables though.
Just spent ages changing keys from float in a datawarehouse - think of a fact table with 100 million rows and all keys floats when they should often be tinyint.

Subject: re: Nice - but a bit pointless
Posted by: Anonymous (not signed in)
Posted on: Wednesday, November 08, 2006 at 4:53 AM
Message:
ok, I understand the cost point - but if you have a serious backup setup, you've probably already got a Backup tool (RG Backup / Litespeed / Backup Exec etc.) and most of them have pretty straightforward log shipping facilities. For most people log shipping isn't straightforward.

- BostonBrian

Subject: invalid bak file
Posted by: Anonymous (not signed in)
Posted on: Thursday, November 09, 2006 at 1:16 AM
Message: We have created something similary to your software.
What happens if your live server creates a backup file that is unusable? Like its 10 GB, when it should have been 20 GB?
Our live system just did that, and our backup system tried to restore it, dropping the valid backup db in the process. So we ended up with 0 valid dbs.
Now we restore to a temp name, and then use a Alter Database xx Modify name = 'yy'
Best regards
Henrik Staun Poulsen

Subject: reply
Posted by: nigelrivett (view profile)
Posted on: Wednesday, December 06, 2006 at 5:23 AM
Message: >> For most people log shipping isn't straightforward.

That's the whole point - it should be.
The concept is pretty simple as is the code needed. Lack of knowledge should not be a reason for not coding it yourself - although there may be other reasons to use a 3rd party application.

Subject: Incremental backups
Posted by: Anonymous (not signed in)
Posted on: Sunday, January 14, 2007 at 1:43 PM
Message: Just a small point about incremental backups... Each one is a backup of all changes since the last full.
It shouldn't be necessary to restore each one in order. Just the last full and the most recent incremental.

Good stuff by the way!!

Subject: Post Script...
Posted by: Anonymous (not signed in)
Posted on: Sunday, January 14, 2007 at 1:46 PM
Message: I'm assuming you're referring to SQL differential backups.

Subject: Using the built in log shipping
Posted by: WiltsUK (not signed in)
Posted on: Monday, January 15, 2007 at 6:05 AM
Message: Just a small point - built in log shipping is only available in the Enterprise version of SQL server (that and the developer version, which of course should not be in production). enterprise is a LOT more expensive than standard, so for the sake of log shipping, this method is cheaper.
Another plus for this method is that it is all in script - there is currently no way of scripting the built in log shipping method. this means that if you have to rebuild it at any time, you have to go through teh wizard. with a little thought, one couold set up a "master script" that would call the other scripts - in other words, you could put back log shipping by calling one script - jobs a good 'un.
Or maybe I'm just an old git myself

Subject: Tradeoffs between log shipping and Replication?
Posted by: Anonymous (not signed in)
Posted on: Friday, February 02, 2007 at 1:25 PM
Message: What are the tradeoffs between this log shipping technique and the builtin Replication (via Publications and Subscriptions) for someone that is using SQL Server Standard?

Subject: Tradeoffs between log shipping and Replication?
Posted by: Anonymous (not signed in)
Posted on: Wednesday, March 14, 2007 at 6:05 PM
Message: Log shipping
Easy to setup
Less resources required
Less network obsessive
Comparitively less expensive
Can be only implemented on database level and not on tables or object level
A little difficult to maintain
Secondary has to be in standby 'read only' mode. Cannot use secondary for write


Replication
A little complex to install but easy to maintain
Can be used at object levels i,e tables and SPs (articles)
You can have multiple subscribers
Can be controlled by either of Primary or secondary
Failover is easy (comparitively)

Subject: Anonymous comments disabled
Posted by: Tony Davis (view profile)
Posted on: Monday, June 18, 2007 at 8:26 AM
Message:

Spam comments are arriving on this article faster than we can remove them: I've been forced to disable anonymous commenting.

Please continue to comment -- but you will need to sign in to do so, or join if you are not a member (see the links at the top right of this page). You just need to provide a username, email address and password.

Simple-Talk does not share email or other details with third parties, under any circumstances.

Best,

Tony.


Subject: Provision for drectories with spaces and database names with spaces
Posted by: koBus (view profile)
Posted on: Monday, August 13, 2007 at 9:40 AM
Message: I inherited a server with log shipping on it. Unfortunately log shipping broke and I could not get it going again. This article was a life saver. It explained how log shipping worked and gave me a way of implementing it again, this time for all the databases that needed it. This also makes life easier if you have to restart log shipping ever again.

Just one thing I noticed. The StoredProcedures does not work if the database name has embedded spaces or if the directory has embedded spaces.

The store procedure s_BackupAllDatabases does not need any adjustment.

So here are the modified StoredProcedures on the target DB server:
s_nrSyncDir and s_restoredatabase

USE [Admin]
GO
/****** Object: StoredProcedure [dbo].[s_nrSyncDir] Script Date: 08/13/2007 16:14:43 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER proc [dbo].[s_nrSyncDir]
@LocalDir1 varchar(128) ,
@LocalDir2 varchar(128) , -- assume files are processed in @LocalDir1 then moved to @LocalDir2 by some other process
@RemoteDir varchar(128) ,
@FileMask varchar(128) ,
@RetainPeriod datetime ,
@debug int = 0
as
/*
exec s_nrSyncDir
@LocalDir1 = 'c:\BackupCopy\MyServer\Log\' ,
@LocalDir2 = 'c:\BackupCopy\MyServer\Log\Archive\' ,
@RemoteDir = '\\MyServer\c$\Backup\Log\' ,
@FileMask = '*.bak' ,
@RetainPeriod = '19000105' -- Only transfer backups created in the last 5 days
*/
declare @cmd varchar(1000) ,
@filename varchar(128) ,
@EarliestRetain varchar(15)

select @EarliestRetain = convert(varchar(8),getdate() - @RetainPeriod, 112) + '_' + replace(convert(varchar(8), getdate() - @RetainPeriod, 108), ':', '')

create table #locdir (s varchar(2000))
create table #remdir (s varchar(2000))

select @cmd = 'dir /B "' + @LocalDir1 + @FileMask + '"'
insert #locdir exec master..xp_cmdshell @cmd

if @debug = 1
select locdir = s from #locdir

if @LocalDir2 is not null
begin
select @cmd = 'dir /B "' + @LocalDir2 + @FileMask + '"'
insert #locdir exec master..xp_cmdshell @cmd


if @debug = 1
select locdir2 = s from #locdir

delete #locdir
where s is null
or s like '%not found%'

-- delete any out of date files in @LocalDir2
select @filename = ''
while @filename < (select max(s) from #locdir)
begin
select @filename = min(s) from #locdir where s > @filename

if left(right(@filename,19),15) < @EarliestRetain
begin
-- delete file
select @cmd = 'del "' + @LocalDir2 + @filename + '"'
select @cmd
exec master..xp_cmdshell @cmd
end
end
end

delete #locdir
where s is null
or s like '%not found%'

-- delete any out of date files @LocalDir1
if @LocalDir2 is null -- If there is a @LocalDir2 then need to leave files until they are processed
begin
select @filename = ''
while @filename < (select max(s) from #locdir)
begin
select @filename = min(s) from #locdir where s > @filename

if left(right(@filename,19),15) < @EarliestRetain
begin
-- delete file
select @cmd = 'del "' + @LocalDir1 + @filename + '"'
select @cmd
exec master..xp_cmdshell @cmd
end
end
end

select @cmd = 'dir /B "' + @RemoteDir + @FileMask + '"'
insert #remdir exec master..xp_cmdshell @cmd


if @debug = 1
select remdir = s from #remdir


delete #remdir
where s is null
or s like '%not found%'

delete #remdir
where left(right(s,19),15) < @EarliestRetain

delete #remdir
from #locdir
where #remdir.s = #locdir.s

drop table #locdir

select @filename = ''
while @filename < (select max(s) from #remdir)
begin
select @filename = min(s) from #remdir where s > @filename

select @cmd = 'xcopy "' + @RemoteDir + @filename + '" "' + @LocalDir1 + '"'
select copyfile = @cmd
exec master..xp_cmdshell @cmd
end





Subject: Continue: Provision for drectories with spaces and database names with spaces
Posted by: koBus (view profile)
Posted on: Monday, August 13, 2007 at 9:42 AM
Message: USE [Admin]
GO
/****** Object: StoredProcedure [dbo].[s_restoredatabase] Script Date: 08/13/2007 16:29:07 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
--s_RestoreDatabase - restore all the databases from a full backup
--and then apply logs

ALTER PROCEDURE [dbo].[s_restoredatabase]
@SourcePath VARCHAR(200), --the location of the backup files
@archivePath VARCHAR(200), --where to archive the backup files
@DataPath VARCHAR(200), --location to restore the data file(s)
@LogPath VARCHAR(200), --location to restore the log file(s)
@recover VARCHAR(10), -- recover, norecovery, standby
@recipients VARCHAR(128) = NULL,
@Database VARCHAR(128) = NULL /* -- only restore
this database */
AS
/*
For this to work, your backup files should be of the
.BAK file type, and the files must have the word
_FULL_ for a full backup or _LOG_ for a log file
Example of use:
exec s_RestoreDatabase
@SourcePath = 'c:\atest' ,
@archivePath = 'c:\atest\archive' ,
@DataPath = 'c:\atest' ,
@LogPath = 'c:\atest' ,
@recover = 'norecovery' ,
@recipients = '' */

/*
Get all files from directory (they will be *.bak).
The process is controlled by the files in the directory.
If there is a full backup then restore it.
If there is a diff then restore it next.
Restore any logs
Recover database if necessary
*/

DECLARE @dbname VARCHAR(128),
@cmd VARCHAR(2000),
@filename VARCHAR(128),
@s VARCHAR(128),
@t VARCHAR(128),
@sql NVARCHAR(2000)

create table #Files
(
lname varchar(128),
pname VARCHAR(128),
type varchar(10),
fgroup varchar(128),
size varchar(50),
maxsize varchar(50),
FileId varchar(10),
CreateLSN varchar(20),
DropLSN varchar(20),
UniqueId varchar(128),
ReadOnlyLSN varchar(20),
ReadWriteLSN varchar(20),
BackupSizeInBytes varchar(20),
SourceBlockSize varchar(20),
FileGroupId varchar(10),
LogGroupGUID varchar(128),
DifferentialBaseLSN varchar(20),
DifferentialBaseGUID varchar(128),
IsReadOnly varchar(10),
IsPresent varchar(10))

CREATE TABLE #dir (
s VARCHAR(2000))
/* -- get list of files in directory */
SELECT @cmd = 'dir /B "' + @SourcePath + '*.bak"'
INSERT #dir
EXEC master..xp_cmdshell @cmd
DELETE #dir --delete anything which is not a backup
WHERE s IS NULL
OR s NOT LIKE '%.bak'
OR (s NOT LIKE '%^_Full^_%' ESCAPE '^'
AND s NOT LIKE '%^_Log^_%' ESCAPE '^')
IF @Database IS NOT NULL --if he has specified a database
DELETE #dir
WHERE s NOT LIKE @Database + '^_%' ESCAPE '^'

/* -- deal with each database in turn */
WHILE EXISTS (SELECT * FROM #dir)
BEGIN
/* -- any with a full first */
SELECT @dbname = NULL
SELECT TOP 1 @dbname = LEFT(s,CHARINDEX('_Full_',s) - 1)
FROM #dir
WHERE CHARINDEX('_Full_',s) <> 0
ORDER BY s
/* -- no full - get log */
IF @dbname IS NULL
BEGIN
SELECT @dbname = NULL
SELECT TOP 1 @dbname = LEFT(s,CHARINDEX('_Log_',s) - 1)
FROM #dir
WHERE CHARINDEX('_Log_',s) <> 0
ORDER BY s
END
/* -- find the last full backup for this db */
SELECT @filename = NULL
SELECT @filename = MAX(s)FROM #dir
WHERE s LIKE @dbname + '_Full_%.bak'
/* -- archive everything for this db that appears
before this file */
SELECT @s = ''
WHILE @s IS NOT NULL AND @filename IS NOT NULL
BEGIN
SELECT TOP 1 @s = s
FROM #dir
WHERE s LIKE @dbname + '%'
ORDER BY RIGHT(s,20)
IF @s = @filename
BEGIN
SELECT @s = NULL
END
ELSE
BEGIN
/* -- move to archive */
SELECT @cmd = 'move "' + @SourcePath
+ @s + '" "' + @archivePath + @s + '"'
EXEC master..xp_cmdshell @cmd
DELETE #dir WHERE s = @s
END
END
/* -- now we can go through each file in turn for this
database and restore it */
WHILE EXISTS
(SELECT * FROM #dir
WHERE s LIKE @dbname + '^_%' ESCAPE '^')
BEGIN
SELECT TOP 1 @filename = s
FROM #dir
WHERE s LIKE @dbname + '^_%' ESCAPE '^'
ORDER BY RIGHT(s,20)
IF @filename LIKE '%^_Full^_%' ESCAPE '^'
BEGIN
/* -- restore a full backup */
IF EXISTS (SELECT *
FROM master..sysdatabases
WHERE name = @dbname)
BEGIN
/* -- Drop the database before starting the restore */
SELECT @cmd = 'drop database ' + @dbname
EXEC( @cmd)
END
SELECT @cmd = 'restore filelistonly from disk = '''
+ @SourcePath + @filename + ''''

DELETE #files
INSERT #files
EXEC( @cmd)
/* -- now build the restore */
SELECT @cmd = NULL, @s = ''
WHILE @s <
(SELECT MAX(lname) FROM #files)
BEGIN
SELECT TOP 1 @s = lname, @t = TYPE
FROM #files
WHERE lname > @s
ORDER BY lname
SELECT @cmd = COALESCE(@cmd + ',move ','')
+ '''' + @s + ''' to '''
+ CASE WHEN @t = 'D' THEN @DataPath
ELSE @LogPath END
+ @s + ''''
END

/*The MOVE is used to relocate the database files
and to avoid collisions with existing files. */

SELECT @cmd = 'restore database '
+ @dbname
+ ' from disk = '''
+ @SourcePath
+ @filename
+ ''' with move '
+ @cmd
+ ', NORECOVERY'
/* -- + ', standby = ''' + @localpath + 'standby.fil''' */
EXEC( @cmd)
END
ELSE
IF @filename LIKE '%^Log^_%' ESCAPE '^'
BEGIN
/* -- restore a log backup */
SELECT @cmd = 'restore log '
+ @dbname
+ ' from disk = '''
+ @SourcePath
+ @filename

+ ''' with NORECOVERY'
EXEC( @cmd)
END
/* -- move to archive */
SELECT @cmd = 'move "'
+ @SourcePath
+ @filename
+ '" "'
+ @archivePath
+ @filename
+ '"'
EXEC master..xp_cmdshell @cmd
DELETE #dir WHERE s = @filename
END
/* -- now set to correct recovey mode */
IF @recover = 'recover'
BEGIN
SELECT @cmd = 'restore database '
+ @dbname
+ ' with recovery'
EXEC( @cmd)
END
END


 









Phil Factor
Bunnikins!
 When an IT manager is selected as a victim of office politics of a large corporate, it is time for him to engage in... Read more...



 View the blog
On the Trail of the Expanding Databases
 It is sometimes difficult for other IT people to understand the constraints that DBAs have to work... Read more...

SQL Server 2008: The New Data Types
 Brad continues his helicopter-level view of the most interesting new features of SQL Server 2008 with a... Read more...

Using Powershell to Generate Table-Creation Scripts
 For all of us who learn best by trying out examples, Bob Sheldon produces a PowerShell script file for... Read more...

SQL Response: The dim sum interview
 Richard Morris met David and Nigel of the SQL Response team, in a dim sum Restaurant in Cambridge. They... Read more...

SQL Toolbelt 2008: Predominantly an Engineering Task
 The conversion of the Red-Gate tools to be compatible with SQL Server 2008 might not seem, on first... Read more...

Beginning SQL Server 2005 Reporting Services Part 1
 Steve Joubert begins an in-depth tour of SQL Server 2005 Reporting Services with a step-by-step guide... Read more...

Ten Common Database Design Mistakes
 Database design and implementation is the cornerstone of any data centric project (read 99.9% of... Read more...

SQL Server Full Text Search Language Features
 SQL Full-text Search (SQL FTS) is an optional component of SQL Server 7 and later, which allows fast... Read more...

Beginning SQL Server 2005 Reporting Services Part 2
 Continuing his in-depth tour of SQL Server 2005 Reporting Services, Steve Joubert demonstrates the most... Read more...

Executing SSIS Packages
 Nigel Rivett demonstrates how to execute all SSIS packages in a given folder using either an SSIS... Read more...

Over 150,000 Microsoft professionals subscribe to the Simple-Talk technical journal. Join today, it's fast, simple, free and secure.

Join Simple Talk