@@ -190,6 +190,8 @@ BEGIN
190190 ,@TraceFileIssue bit
191191 -- Flag for Windows OS to help with Linux support
192192 ,@IsWindowsOperatingSystem BIT
193+ -- Flag for Azure SQL Database (EngineEdition 5) to skip checks that do not apply
194+ ,@IsAzureSQLDB BIT
193195 ,@DaysUptime NUMERIC (23 ,2 )
194196 /* For First Responder Kit consistency check:*/
195197 ,@spBlitzFullName VARCHAR (1024 )
@@ -746,6 +748,9 @@ BEGIN
746748 SELECT @IsWindowsOperatingSystem = 1 ;
747749 END ;
748750
751+ -- Flag for Azure SQL Database - used to guard email and linked server output paths
752+ SELECT @IsAzureSQLDB = CASE WHEN CONVERT (INT , SERVERPROPERTY (' EngineEdition' )) = 5 THEN 1 ELSE 0 END ;
753+
749754
750755 IF NOT EXISTS ( SELECT 1
751756 FROM #SkipChecks
@@ -922,6 +927,90 @@ BEGIN
922927 ' Managed Instance detected, so we skipped some checks that are not currently possible, relevant, or practical there.' AS Details;
923928 END ; /* Azure Managed Instance skipped checks */
924929
930+ /* If the server is Azure SQL Database, skip checks that it doesn't allow */
931+ IF SERVERPROPERTY (' EngineEdition' ) = 5
932+ BEGIN
933+ /* Backup / restore history - msdb does not exist on Azure SQL DB */
934+ INSERT INTO #SkipChecks (CheckID) VALUES (1 ); /* Full backups */
935+ INSERT INTO #SkipChecks (CheckID) VALUES (2 ); /* Log backups */
936+ INSERT INTO #SkipChecks (CheckID) VALUES (4 ); /* Full backup of user DB */
937+ INSERT INTO #SkipChecks (CheckID) VALUES (5 ); /* Log backup of user DB */
938+ INSERT INTO #SkipChecks (CheckID) VALUES (18 ); /* Backup to same drive */
939+ INSERT INTO #SkipChecks (CheckID) VALUES (177 ); /* Disabled Internal Monitoring Features - requires dm_server_registry access */
940+ INSERT INTO #SkipChecks (CheckID) VALUES (186 ); /* MSDB Backup History Purged Too Frequently */
941+
942+ /* SQL Agent - no Agent on Azure SQL DB */
943+ INSERT INTO #SkipChecks (CheckID) VALUES (6 ); /* Jobs Owned By Users */
944+ INSERT INTO #SkipChecks (CheckID) VALUES (30 ); /* Alerts not configured */
945+ INSERT INTO #SkipChecks (CheckID) VALUES (31 ); /* No enabled operators */
946+ INSERT INTO #SkipChecks (CheckID) VALUES (57 ); /* Agent Job Runs at Startup */
947+ INSERT INTO #SkipChecks (CheckID) VALUES (59 ); /* Alerts Configured without Follow Up */
948+ INSERT INTO #SkipChecks (CheckID) VALUES (61 ); /* Agent alerts for severity 19-25 */
949+ INSERT INTO #SkipChecks (CheckID) VALUES (73 ); /* No Failsafe Operator Configured */
950+ INSERT INTO #SkipChecks (CheckID) VALUES (79 ); /* Shrink Database Job */
951+ INSERT INTO #SkipChecks (CheckID) VALUES (94 ); /* Job failure without operator notification */
952+ INSERT INTO #SkipChecks (CheckID) VALUES (96 ); /* Agent alerts for corruption */
953+ INSERT INTO #SkipChecks (CheckID) VALUES (98 ); /* Disabled alerts */
954+ INSERT INTO #SkipChecks (CheckID) VALUES (123 ); /* Agent Jobs Starting Simultaneously */
955+ INSERT INTO #SkipChecks (CheckID) VALUES (180 ); /* Maintenance plans */
956+ INSERT INTO #SkipChecks (CheckID) VALUES (181 ); /* Repetitive maintenance tasks */
957+ INSERT INTO #SkipChecks (CheckID) VALUES (219 ); /* Alerts without event descriptions */
958+
959+ /* Cross-DB / system-DB access not permitted on Azure SQL DB */
960+ INSERT INTO #SkipChecks (CheckID) VALUES (29 ); /* Tables in model database */
961+ INSERT INTO #SkipChecks (CheckID) VALUES (55 ); /* Database owner <> sa - queries master.sys */
962+ INSERT INTO #SkipChecks (CheckID) VALUES (68 ); /* Last good DBCC CHECKDB - DBCC DBINFO cross-DB */
963+ INSERT INTO #SkipChecks (CheckID) VALUES (69 ); /* High VLF count - DBCC LOGINFO cross-DB */
964+ INSERT INTO #SkipChecks (CheckID) VALUES (71 ); /* sysadmin in master.sys.syslogins */
965+ INSERT INTO #SkipChecks (CheckID) VALUES (74 ); /* Trace flags - DBCC TRACESTATUS */
966+ INSERT INTO #SkipChecks (CheckID) VALUES (97 ); /* Unusual SQL Server Edition */
967+ INSERT INTO #SkipChecks (CheckID) VALUES (2301 ); /* sp_validatelogins */
968+
969+ /* File layout / tempdb - cannot read tempdb or system DBs cross-DB from a user DB */
970+ INSERT INTO #SkipChecks (CheckID) VALUES (21 ); /* Database encrypted - always true on Azure SQL DB */
971+ INSERT INTO #SkipChecks (CheckID) VALUES (24 ); /* System DB on C drive */
972+ INSERT INTO #SkipChecks (CheckID) VALUES (40 ); /* TempDB only one data file */
973+ INSERT INTO #SkipChecks (CheckID) VALUES (41 ); /* TempDB file size/growth mismatch */
974+ INSERT INTO #SkipChecks (CheckID, DatabaseName) VALUES (80 , ' master' ); /* Max file size set */
975+ INSERT INTO #SkipChecks (CheckID, DatabaseName) VALUES (80 , ' model' ); /* Max file size set */
976+ INSERT INTO #SkipChecks (CheckID, DatabaseName) VALUES (80 , ' msdb' ); /* Max file size set */
977+ INSERT INTO #SkipChecks (CheckID, DatabaseName) VALUES (80 , ' tempdb' ); /* Max file size set */
978+ INSERT INTO #SkipChecks (CheckID) VALUES (172 ); /* TempDB files on C drive */
979+
980+ /* Server / OS / services - not addressable on Azure SQL DB */
981+ INSERT INTO #SkipChecks (CheckID) VALUES (50 ); /* Max Server Memory - not user-configurable */
982+ INSERT INTO #SkipChecks (CheckID) VALUES (92 ); /* Drive space - xp_fixeddrives */
983+ INSERT INTO #SkipChecks (CheckID) VALUES (100 ); /* Remote DAC */
984+ INSERT INTO #SkipChecks (CheckID) VALUES (192 ); /* IFI - not applicable */
985+ INSERT INTO #SkipChecks (CheckID) VALUES (193 ); /* xp_readerrorlog for IFI */
986+ INSERT INTO #SkipChecks (CheckID) VALUES (199 ); /* Default trace */
987+ INSERT INTO #SkipChecks (CheckID) VALUES (211 ); /* Power plan - xp_regread */
988+ INSERT INTO #SkipChecks (CheckID) VALUES (212 ); /* Additional instances - xp_regread */
989+ INSERT INTO #SkipChecks (CheckID) VALUES (224 ); /* SSRS/SSAS/SSIS Installed */
990+ INSERT INTO #SkipChecks (CheckID) VALUES (258 ); /* SQL Server service running as LocalSystem */
991+ INSERT INTO #SkipChecks (CheckID) VALUES (259 ); /* Agent service running as LocalSystem */
992+ INSERT INTO #SkipChecks (CheckID) VALUES (260 ); /* SQL Server service account in Administrators */
993+ INSERT INTO #SkipChecks (CheckID) VALUES (261 ); /* Agent service account in Administrators */
994+
995+ /* Replication / mirroring / AGs - not applicable on Azure SQL DB */
996+ INSERT INTO #SkipChecks (CheckID) VALUES (227 ); /* Database Mirroring */
997+
998+ INSERT INTO #BlitzResults
999+ ( CheckID ,
1000+ Priority ,
1001+ FindingsGroup ,
1002+ Finding ,
1003+ URL ,
1004+ Details
1005+ )
1006+ SELECT 223 AS CheckID ,
1007+ 0 AS Priority ,
1008+ ' Informational' AS FindingsGroup ,
1009+ ' Some Checks Skipped' AS Finding ,
1010+ ' https://learn.microsoft.com/en-us/azure/azure-sql/database/' AS URL ,
1011+ ' Azure SQL Database detected, so we skipped some checks that are not currently possible, relevant, or practical there.' AS Details;
1012+ END ; /* Azure SQL Database skipped checks */
1013+
9251014 /*
9261015 That's the end of the SkipChecks stuff.
9271016 The next several tables are used by various checks later.
@@ -9844,7 +9933,7 @@ IF NOT EXISTS ( SELECT 1
98449933 DROP TABLE IF EXISTS #MasterFiles;
98459934 CREATE TABLE #MasterFiles (database_id INT , file_id INT , type_desc NVARCHAR (50 ), name NVARCHAR (255 ), physical_name NVARCHAR (255 ), size BIGINT );
98469935 /* Azure SQL Database doesn't have sys.master_files, so we have to build our own. */
9847- IF (( SERVERPROPERTY (' Edition ' )) = ' SQL Azure'
9936+ IF (CONVERT ( INT , SERVERPROPERTY (' EngineEdition ' )) = 5
98489937 AND (OBJECT_ID (' sys.master_files' ) IS NULL ))
98499938 SET @StringToExecute = ' INSERT INTO #MasterFiles (database_id, file_id, type_desc, name, physical_name, size) SELECT DB_ID(), file_id, type_desc, name, physical_name, size FROM sys.database_files;' ;
98509939 ELSE
@@ -10134,44 +10223,53 @@ IF NOT EXISTS ( SELECT 1
1013410223
1013510224 IF @EmailRecipients IS NOT NULL
1013610225 BEGIN
10137-
10138- IF @Debug IN (1 , 2 ) RAISERROR (' Sending an email.' , 0 , 1 ) WITH NOWAIT ;
10139-
10140- /* Database mail won't work off a local temp table. I'm not happy about this hacky workaround either. */
10141- IF (OBJECT_ID (' tempdb..##BlitzResults' , ' U' ) IS NOT NULL ) DROP TABLE ##BlitzResults;
10142- SELECT * INTO ##BlitzResults FROM #BlitzResults;
10143- SET @query_result_separator = char (9 );
10144- SET @StringToExecute = ' SET NOCOUNT ON;SELECT [Priority] , [FindingsGroup] , [Finding] , [DatabaseName] , [URL] , [Details] , CheckID FROM ##BlitzResults ORDER BY Priority , FindingsGroup , Finding , DatabaseName , Details; SET NOCOUNT OFF;' ;
10145- SET @EmailSubject = ' sp_Blitz Results for ' + @@SERVERNAME ;
10146- SET @EmailBody = ' sp_Blitz ' + CAST (CONVERT (DATETIME , @VersionDate, 102 ) AS VARCHAR (100 )) + ' . http://FirstResponderKit.org' ;
10147- IF @EmailProfile IS NULL
10148- EXEC msdb .dbo .sp_send_dbmail
10149- @recipients = @EmailRecipients,
10150- @subject = @EmailSubject,
10151- @body = @EmailBody,
10152- @query_attachment_filename = ' sp_Blitz-Results.csv' ,
10153- @attach_query_result_as_file = 1 ,
10154- @query_result_header = 1 ,
10155- @query_result_width = 32767 ,
10156- @append_query_error = 1 ,
10157- @query_result_no_padding = 1 ,
10158- @query_result_separator = @query_result_separator,
10159- @query = @StringToExecute;
10226+
10227+ IF @IsAzureSQLDB = 1
10228+ BEGIN
10229+ IF @Debug IN (1 , 2 ) RAISERROR (' Skipping email - Database Mail is not available on Azure SQL Database.' , 0 , 1 ) WITH NOWAIT ;
10230+ PRINT ' Email output is not supported on Azure SQL Database (Database Mail / msdb.dbo.sp_send_dbmail is unavailable). Skipping email send.' ;
10231+ END ;
1016010232 ELSE
10161- EXEC msdb .dbo .sp_send_dbmail
10162- @profile_name = @EmailProfile,
10163- @recipients = @EmailRecipients,
10164- @subject = @EmailSubject,
10165- @body = @EmailBody,
10166- @query_attachment_filename = ' sp_Blitz-Results.csv' ,
10167- @attach_query_result_as_file = 1 ,
10168- @query_result_header = 1 ,
10169- @query_result_width = 32767 ,
10170- @append_query_error = 1 ,
10171- @query_result_no_padding = 1 ,
10172- @query_result_separator = @query_result_separator,
10173- @query = @StringToExecute;
10174- IF (OBJECT_ID (' tempdb..##BlitzResults' , ' U' ) IS NOT NULL ) DROP TABLE ##BlitzResults;
10233+ BEGIN
10234+
10235+ IF @Debug IN (1 , 2 ) RAISERROR (' Sending an email.' , 0 , 1 ) WITH NOWAIT ;
10236+
10237+ /* Database mail won't work off a local temp table. I'm not happy about this hacky workaround either. */
10238+ IF (OBJECT_ID (' tempdb..##BlitzResults' , ' U' ) IS NOT NULL ) DROP TABLE ##BlitzResults;
10239+ SELECT * INTO ##BlitzResults FROM #BlitzResults;
10240+ SET @query_result_separator = char (9 );
10241+ SET @StringToExecute = ' SET NOCOUNT ON;SELECT [Priority] , [FindingsGroup] , [Finding] , [DatabaseName] , [URL] , [Details] , CheckID FROM ##BlitzResults ORDER BY Priority , FindingsGroup , Finding , DatabaseName , Details; SET NOCOUNT OFF;' ;
10242+ SET @EmailSubject = ' sp_Blitz Results for ' + @@SERVERNAME ;
10243+ SET @EmailBody = ' sp_Blitz ' + CAST (CONVERT (DATETIME , @VersionDate, 102 ) AS VARCHAR (100 )) + ' . http://FirstResponderKit.org' ;
10244+ IF @EmailProfile IS NULL
10245+ EXEC msdb .dbo .sp_send_dbmail
10246+ @recipients = @EmailRecipients,
10247+ @subject = @EmailSubject,
10248+ @body = @EmailBody,
10249+ @query_attachment_filename = ' sp_Blitz-Results.csv' ,
10250+ @attach_query_result_as_file = 1 ,
10251+ @query_result_header = 1 ,
10252+ @query_result_width = 32767 ,
10253+ @append_query_error = 1 ,
10254+ @query_result_no_padding = 1 ,
10255+ @query_result_separator = @query_result_separator,
10256+ @query = @StringToExecute;
10257+ ELSE
10258+ EXEC msdb .dbo .sp_send_dbmail
10259+ @profile_name = @EmailProfile,
10260+ @recipients = @EmailRecipients,
10261+ @subject = @EmailSubject,
10262+ @body = @EmailBody,
10263+ @query_attachment_filename = ' sp_Blitz-Results.csv' ,
10264+ @attach_query_result_as_file = 1 ,
10265+ @query_result_header = 1 ,
10266+ @query_result_width = 32767 ,
10267+ @append_query_error = 1 ,
10268+ @query_result_no_padding = 1 ,
10269+ @query_result_separator = @query_result_separator,
10270+ @query = @StringToExecute;
10271+ IF (OBJECT_ID (' tempdb..##BlitzResults' , ' U' ) IS NOT NULL ) DROP TABLE ##BlitzResults;
10272+ END ;
1017510273 END ;
1017610274
1017710275 /* Checks if @OutputServerName is populated with a valid linked server, and that the database name specified is valid */
@@ -10180,11 +10278,18 @@ IF NOT EXISTS ( SELECT 1
1018010278 DECLARE @LinkedServerDBCheck NVARCHAR (2000 );
1018110279 DECLARE @ValidLinkedServerDB INT ;
1018210280 DECLARE @tmpdbchk table (cnt int );
10183- IF @OutputServerName IS NOT NULL
10281+ IF @OutputServerName IS NOT NULL AND @IsAzureSQLDB = 1
1018410282 BEGIN
10185-
10283+ IF @Debug IN (1 , 2 ) RAISERROR (' Skipping linked server output - not supported on Azure SQL Database.' , 0 , 1 ) WITH NOWAIT ;
10284+ PRINT ' Linked server output (@OutputServerName) is not supported on Azure SQL Database. Skipping remote output.' ;
10285+ SET @ValidOutputServer = 0 ;
10286+ SET @ValidOutputLocation = 0 ;
10287+ END ;
10288+ ELSE IF @OutputServerName IS NOT NULL
10289+ BEGIN
10290+
1018610291 IF @Debug IN (1 , 2 ) RAISERROR (' Outputting to a remote server.' , 0 , 1 ) WITH NOWAIT ;
10187-
10292+
1018810293 IF EXISTS (SELECT server_id FROM sys .servers WHERE QUOTENAME ([name]) = @OutputServerName)
1018910294 BEGIN
1019010295 SET @LinkedServerDBCheck = ' SELECT 1 WHERE EXISTS (SELECT * FROM '+ @OutputServerName+ ' .master.sys.databases WHERE QUOTENAME([name]) = '' '+ @OutputDatabaseName+ ' '' )' ;
0 commit comments