-
Notifications
You must be signed in to change notification settings - Fork 9
Expand file tree
/
Copy pathRestoreCommand.sql
More file actions
233 lines (188 loc) · 6.84 KB
/
RestoreCommand.sql
File metadata and controls
233 lines (188 loc) · 6.84 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[RestoreCommand]') AND type in (N'P', N'PC'))
DROP PROCEDURE [dbo].[RestoreCommand]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[RestoreCommand]') AND type in (N'P', N'PC'))
BEGIN
EXEC dbo.sp_executesql @statement = N'CREATE PROCEDURE [dbo].[RestoreCommand] AS'
END
GO
ALTER PROCEDURE [dbo].[RestoreCommand] AS
/*************************************************************************************************************
Script for creating automated restore scripts based on Ola Hallengren's Maintenance Solution.
Source: https://ola.hallengren.com
Create RestoreCommand s proc in location of Maintenance Solution procedures
and CommandLog table along with creating job steps.
At least one full backup for all databases should be logged to CommandLog table (i.e., executed through Maintenance Solution
created FULL backup job) for generated restore scripts to be valid.
Restore scripts are generated based on CommandLog table, not msdb backup history.
Restore script is created using ouput file. Each backup job creates a date / time stamped restore script file in separate step.
Add a job to manage file retention if desired (I use a modified version of Ola's Output File Cleanup job).
If possible, perform a tail log backup and add to end of restore script
in order to avoid data loss (also remove any replace options for full backups).
Make sure sql agent has read / write to the directory that you want the restore script created.
Script will read backup file location from @Directory value used in respective DatabaseBackup job (NULL is supported).
Set @LogToTable = 'Y' for all backup jobs! (This is the defaut).
Created by Jared Zagelbaum, 4/13/2015, https://jaredzagelbaum.wordpress.com/
For intro / tutorial see: https://jaredzagelbaum.wordpress.com/2015/04/16/automated-restore-script-output-for-ola-hallengrens-maintenance-solution/
Follow me on Twitter!: @JaredZagelbaum
**************************************************************************************************************/
SET NOCOUNT ON
Declare @DatabaseName sysname
Declare @DatabaseNamePartition sysname = 'N/A'
Declare @Command nvarchar(max)
Declare @IncludeCopyOnly nvarchar(max) = 'Y' -- include copy only backups in restore script? Added for AlwaysOn support
Declare @message nvarchar(max)
Declare restorecursor CURSOR FAST_FORWARD FOR
with completed_ola_backups as
(
SELECT [ID]
,[DatabaseName]
,[SchemaName]
,[ObjectName]
,[ObjectType]
,[IndexName]
,[IndexType]
,[StatisticsName]
,[PartitionNumber]
,[ExtendedInfo]
,[Command]
,[CommandType]
,[StartTime]
,[EndTime]
,[ErrorNumber]
,[ErrorMessage]
,CASE WHEN [Command] LIKE '%\LOG\%' THEN 'Log'
WHEN @IncludeCopyOnly = 'Y' AND [Command] LIKE '%\LOG_COPY_ONLY\%' THEN 'Log'
WHEN [Command] LIKE '%\DIFF\%' THEN 'Diff'
WHEN [Command] LIKE '%\FULL\%' THEN 'Full'
WHEN @IncludeCopyOnly = 'Y' AND [Command] LIKE '%\FULL_COPY_ONLY\%' THEN 'Full'
End BackupType
,CASE WHEN [Command] LIKE '%\LOG\%' THEN 3
WHEN @IncludeCopyOnly = 'Y' AND [Command] LIKE '%\LOG_COPY_ONLY\%' THEN 3
WHEN [Command] LIKE '%\DIFF\%' THEN 2
WHEN [Command] LIKE '%\FULL\%' THEN 1
WHEN @IncludeCopyOnly = 'Y' AND [Command] LIKE '%\FULL_COPY_ONLY\%' THEN 1
End BackupTypeOrder
,CASE CommandType
WHEN 'BACKUP_LOG'
THEN CHARINDEX('.trn', Command)
WHEN 'BACKUP_DATABASE'
THEN CHARINDEX('.bak', Command)
END filechar
FROM [dbo].[CommandLog]
WHERE CommandType IN ('BACKUP_LOG', 'BACKUP_DATABASE')
AND EndTime IS NOT NULL -- Completed Backups Only
AND ErrorNumber = 0
)
,lastfull as
(
SELECT MAX( [id]) FullId
,DatabaseName
FROM completed_ola_backups
WHERE BackupType = 'Full'
GROUP BY DatabaseName
)
,lastdiff as
(
SELECT MAX( [id]) DiffId
,cob.DatabaseName
FROM completed_ola_backups cob
INNER JOIN lastfull lf
ON cob.DatabaseName = lf.DatabaseName
AND cob.[ID] > lf.FullId
WHERE BackupType = 'Diff'
GROUP BY cob.DatabaseName
)
,lastnonlog as
(
SELECT Max([Id]) LogIdBoundary
,DatabaseName
FROM
(
SELECT Fullid Id, DatabaseName
FROM lastfull
UNION ALL
SELECT DiffId Id, ld.DatabaseName
FROM lastdiff ld
) Nonlog
GROUP BY DatabaseName
)
,lastlogs as
(
SELECT cob.[Id] logid
FROM completed_ola_backups cob
INNER JOIN lastnonlog lnl
ON cob.DatabaseName = lnl.DatabaseName
AND cob.[ID] > lnl.LogIdBoundary
)
,validbackups as
(
SELECT FullId backupid
FROM lastfull
UNION
SELECT DiffId backupid
FROM lastdiff
UNION
SELECT logid backupid
FROM lastlogs
)
SELECT cob.DatabaseName
,
Replace(
Replace(
Replace(
LEFT(Command, filechar + 3)
, 'BACKUP LOG', 'RESTORE LOG')
, 'BACKUP DATABASE', 'RESTORE DATABASE')
, 'TO DISK', 'FROM DISK') + ''' WITH NORECOVERY'
+ CASE BackupType
WHEN 'Full'
THEN ', REPLACE;'
ELSE ';'
END RestoreCommand
FROM completed_ola_backups cob
WHERE EXISTS
(SELECT *
FROM validbackups vb
WHERE cob.[ID] = vb.backupid
)
ORDER BY cob.DatabaseName, Id, BackupTypeOrder
;
RAISERROR( '/*****************************************************************', 10, 1) WITH NOWAIT
set @message = 'Emergency Script Restore for ' + @@Servername + CASE @@Servicename WHEN 'MSSQLSERVER' THEN '' ELSE '\' + @@Servicename END
RAISERROR(@message,10,1) WITH NOWAIT
set @message = 'Generated ' + convert(nvarchar, getdate(), 9)
RAISERROR(@message,10,1) WITH NOWAIT
set @message = 'Script does not perform a tail log backup. Dataloss may occur, use only for emergency DR.'
RAISERROR(@message,10,1) WITH NOWAIT
RAISERROR( '******************************************************************/', 10, 1) WITH NOWAIT
OPEN RestoreCursor
FETCH NEXT FROM restorecursor
INTO @databasename, @command
WHILE @@FETCH_STATUS = 0
BEGIN
IF @DatabaseName <> @DatabaseNamePartition AND @DatabaseNamePartition <> 'N/A'
BEGIN
set @message = 'RESTORE DATABASE ' + '[' + @DatabaseNamePartition + ']' + ' WITH RECOVERY;'
RAISERROR(@message,10,1) WITH NOWAIT
END
IF @DatabaseName <> @DatabaseNamePartition
BEGIN
set @message = char(13) + char(10) + char(13) + char(10) + '--------' + @DatabaseName + '-------------'
RAISERROR(@message,10,1) WITH NOWAIT
END
RAISERROR( @Command,10,1) WITH NOWAIT
SET @DatabaseNamePartition = @DatabaseName
FETCH NEXT FROM restorecursor
INTO @databasename, @command
END
set @message = 'RESTORE DATABASE ' + '[' + @DatabaseNamePartition + ']' + ' WITH RECOVERY;'
RAISERROR(@message,10,1) WITH NOWAIT
;
CLOSE restorecursor;
DEALLOCATE restorecursor;
GO