Skip to content

Commit 90c250f

Browse files
committed
Add stored procedures and script
1 parent a99378c commit 90c250f

File tree

5 files changed

+1208
-0
lines changed

5 files changed

+1208
-0
lines changed
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
--UnPivot The Output Of RESTORE HEADERONLY
2+
--Author: Dave Mason
3+
--Link:http://itsalljustelectrons.blogspot.ru/2017/02/Unpivot-Output-Of-RESTORE-HEADERONLY.html
4+
5+
--create a reusable TABLE TYPE
6+
CREATE TYPE dbo.Header_Only AS TABLE (
7+
BackupName nvarchar(128),
8+
BackupDescription nvarchar(255),
9+
BackupType smallint,
10+
ExpirationDate datetime,
11+
Compressed BIT,
12+
Position smallint,
13+
DeviceType tinyint,
14+
UserName nvarchar(128),
15+
ServerName nvarchar(128),
16+
DatabaseName nvarchar(128),
17+
DatabaseVersion int,
18+
DatabaseCreationDate datetime,
19+
BackupSize numeric(20,0),
20+
FirstLSN numeric(25,0),
21+
LastLSN numeric(25,0),
22+
CheckpointLSN numeric(25,0),
23+
DatabaseBackupLSN numeric(25,0),
24+
BackupStartDate datetime,
25+
BackupFinishDate datetime,
26+
SortOrder smallint,
27+
CodePage smallint,
28+
UnicodeLocaleId int,
29+
UnicodeComparisonStyle int,
30+
CompatibilityLevel tinyint,
31+
SoftwareVendorId int,
32+
SoftwareVersionMajor int,
33+
SoftwareVersionMinor int,
34+
SoftwareVersionBuild int,
35+
MachineName nvarchar(128),
36+
Flags int,
37+
BindingID uniqueidentifier,
38+
RecoveryForkID uniqueidentifier,
39+
Collation nvarchar(128),
40+
FamilyGUID uniqueidentifier,
41+
HasBulkLoggedData bit,
42+
IsSnapshot bit,
43+
IsReadOnly bit,
44+
IsSingleUser bit,
45+
HasBackupChecksums bit,
46+
IsDamaged bit,
47+
BeginsLogChain bit,
48+
HasIncompleteMetaData bit,
49+
IsForceOffline bit,
50+
IsCopyOnly bit,
51+
FirstRecoveryForkID uniqueidentifier,
52+
ForkPointLSN numeric(25,0) NULL,
53+
RecoveryModel nvarchar(60),
54+
DifferentialBaseLSN numeric(25,0) NULL,
55+
DifferentialBaseGUID uniqueidentifier,
56+
BackupTypeDescription nvarchar(60),
57+
BackupSetGUID uniqueidentifier NULL,
58+
CompressedBackupSize bigint,
59+
containment tinyint not NULL
60+
)
61+
GO
62+
63+
--create a temp table, and insert the output of the RESTORE HEADERONLY statement into it via EXEC and a "RESTORE" string
64+
DECLARE @HO AS dbo.Header_Only;
65+
66+
SELECT *
67+
INTO #HO
68+
FROM @HO
69+
WHERE 1 = 2
70+
71+
INSERT INTO #HO
72+
EXEC ('RESTORE HEADERONLY FROM DISK = N''D:\Backup\SomeApp9_Template.bak'' ')
73+
74+
75+
-- build a dynamic T-SQL query by iterating through the column names of the temp table (well, actually of the table type).
76+
--The end result is a bunch of queries that select a static string (field name) and a single column (field value) from the temp table, UNION'ed together.
77+
--The last "UNION ALL" is trimmed from the string. And the string is executed
78+
DECLARE @TSql VARCHAR(MAX) = '';
79+
SELECT
80+
@TSql = @TSql + 'SELECT ''' + c.name + ''' AS [Field], CAST([' + c.name + '] AS VARCHAR(MAX)) AS [Value] FROM #HO UNION ALL' + CHAR(13) + CHAR(10)
81+
FROM sys.table_types t
82+
JOIN sys.columns c
83+
on c.object_id = t.type_table_object_id
84+
WHERE t.name = 'Header_Only'
85+
ORDER BY c.column_id
86+
87+
SET @TSql = LEFT(@TSql, LEN(@TSql) - 11) + CHAR(13) + CHAR(10)
88+
89+
EXEC (@TSql)
90+
91+
DROP TABLE #HO
Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
GO
2+
/****** Object: StoredProcedure [dbo].[spDBA_job_notification] Script Date: 2/3/2017 7:50:51 AM ******/
3+
SET ANSI_NULLS ON;
4+
GO
5+
SET QUOTED_IDENTIFIER ON;
6+
GO
7+
ALTER PROCEDURE [dbo].[spDBA_job_notification]
8+
@jobid UNIQUEIDENTIFIER
9+
AS /*********************************************************************************************************
10+
Purpose: SQL Job Agent does not send the error messages on failure,
11+
so this procedure queries msdb to for the error message and sends an email.
12+
13+
usage: EXEC spDBA_job_notification $(ESCAPE_NONE(JOBID)) SQL2005 SP1 +
14+
********************************************************************************************************/
15+
SET NOCOUNT ON;
16+
DECLARE @Today DATETIME
17+
,@CrLf VARCHAR(10)
18+
,@stat_Failed TINYINT
19+
,@stat_Succeeded TINYINT
20+
,@stat_Retry TINYINT
21+
,@stat_Canceled TINYINT
22+
,@stat_In_progress TINYINT;
23+
DECLARE @Email_To NVARCHAR(100) = 'You@youremailhost.ext'
24+
,@Email_From NVARCHAR(50)
25+
,@subject VARCHAR(200)
26+
,@Body VARCHAR(8000);
27+
DECLARE @jobname sysname
28+
,@stepname sysname
29+
,@Err_severity INT
30+
,@run_datetime DATETIME
31+
,@DBname sysname
32+
,@command VARCHAR(3200)
33+
,@ErrMessage VARCHAR(1024)
34+
,@retry BIT = 0;
35+
SET @Body = '';
36+
SET @CrLf = CHAR(10);
37+
--constants for Job Status execution:
38+
SET @stat_Failed = 0;
39+
SET @stat_Succeeded = 1;
40+
SET @stat_Retry = 2;
41+
SET @stat_Canceled = 3;
42+
SET @stat_In_progress = 4;
43+
SET @Today = GETDATE();
44+
45+
DECLARE curFailedJobs CURSOR READ_ONLY FAST_FORWARD
46+
FOR
47+
SELECT sj.name
48+
,sjh.step_name
49+
,sjh.sql_severity
50+
,sjs.database_name
51+
,run_datetime = CONVERT(DATETIME, LEFT(run_date, 4) + '/'
52+
+ SUBSTRING(run_date, 5, 2) + '/' + RIGHT(run_date, 2) + ' '
53+
+ LEFT(run_time, 2) + ':' + SUBSTRING(run_time, 3, 2) + ':'
54+
+ RIGHT(run_time, 2))
55+
,sjs.command
56+
,sjh.message
57+
FROM msdb..sysjobs sj
58+
JOIN ( SELECT instance_id
59+
,job_id
60+
,step_id
61+
,step_name
62+
,sql_message_id
63+
,sql_severity
64+
,message
65+
,run_status
66+
,run_duration
67+
,operator_id_emailed
68+
,operator_id_netsent
69+
,operator_id_paged
70+
,retries_attempted
71+
,server
72+
,run_date = CONVERT(VARCHAR(8), run_date)
73+
,run_time = CASE WHEN LEN(CONVERT(VARCHAR(8), run_time)) = 5
74+
THEN '0'
75+
+ CONVERT(VARCHAR(8), run_time)
76+
ELSE CONVERT(VARCHAR(8), run_time)
77+
END
78+
FROM msdb..sysjobhistory
79+
) sjh ON sj.job_id = sjh.job_id
80+
JOIN msdb..sysjobsteps sjs ON sjs.job_id = sjh.job_id
81+
AND sjs.step_id = sjh.step_id
82+
83+
-- sjh_Min contains the most recent instance_id (an identity column) from where we should start checking for any failed status records.
84+
JOIN (
85+
-- to account for when there is are multiple log history
86+
SELECT job_id
87+
,instance_id = MAX(instance_id)
88+
FROM msdb..sysjobhistory
89+
WHERE job_id = @jobid
90+
AND step_id = 0
91+
GROUP BY job_id
92+
UNION
93+
-- to account for when you run the job for the first time, there is no history, there will not be any records where the step_id=0.
94+
SELECT job_id
95+
,instance_id = MIN(instance_id)
96+
FROM msdb..sysjobhistory
97+
WHERE job_id = @jobid
98+
AND NOT EXISTS ( SELECT *
99+
FROM msdb..sysjobhistory
100+
WHERE job_id = @jobid
101+
AND step_id = 0 )
102+
GROUP BY job_id
103+
) sjh_Min ON sjh_Min.job_id = sj.job_id
104+
AND sjh.instance_id > sjh_Min.instance_id -- we only want the most recent error message(s).
105+
WHERE sj.job_id = @jobid
106+
AND sjh.step_id <> 0 --exclude the job outcome step
107+
AND sjh.run_status IN ( @stat_Failed ) --filter for only failed status
108+
ORDER BY sjh.instance_id;
109+
110+
OPEN curFailedJobs;
111+
FETCH NEXT FROM curFailedJobs INTO @jobname, @stepname, @Err_severity,
112+
@DBname, @run_datetime, @command, @ErrMessage;
113+
WHILE @@fetch_status = 0
114+
BEGIN
115+
-- Build the Email Body
116+
SET @Body = @Body + 'Step name= ' + @stepname + @CrLf
117+
+ 'DB Name = ' + CONVERT(VARCHAR(50), ISNULL(@DBname, ''))
118+
+ @CrLf + 'Run Date = ' + CONVERT(VARCHAR(50), @run_datetime)
119+
+ @CrLf;
120+
121+
IF ( @Err_severity <> 0 )
122+
SET @Body = @Body + 'Severity = '
123+
+ CONVERT(VARCHAR(10), @Err_severity) + @CrLf;
124+
125+
SET @Body = @Body + 'Error = ' + ISNULL(@ErrMessage, '')
126+
+ @CrLf + @CrLf + 'Command = ' + ISNULL(@command, '') + @CrLf;
127+
128+
FETCH NEXT FROM curFailedJobs INTO @jobname, @stepname,
129+
@Err_severity, @DBname, @run_datetime, @command, @ErrMessage;
130+
END;
131+
CLOSE curFailedJobs;
132+
DEALLOCATE curFailedJobs;
133+
134+
-- Send the Email
135+
IF ( RTRIM(@Body) <> '' )
136+
BEGIN
137+
SET @subject = 'ALERT: ' + @jobname + ' FAILED on \\'
138+
+ @@servername;
139+
SET @Body = -- 'Server= ' + @@servername + @CrLf +
140+
'Job_name = ' + @jobname + @CrLf
141+
+ '--------------------------------------' + @CrLf + @Body;
142+
143+
144+
EXEC msdb.dbo.sp_send_dbmail @profile_name = 'DBMAILPROFILE',
145+
@recipients = @Email_To, @subject = @subject, @body = @Body;
146+
147+
END;

0 commit comments

Comments
 (0)