Top 3 Table Row count report via email alert in SQL Server

 DECLARE @command VARCHAR(5000),@cmd Varchar (1000),@profile_name Varchar(1000)  

DECLARE @xml NVARCHAR(MAX)  

DECLARE @body NVARCHAR(MAX)  

DECLARE @Max_Records TABLE (

[DB_name] [nvarchar](128) NULL,

[SchemaName] [sysname] NOT NULL,

[TableName] [sysname] NOT NULL,

[RowCounts] [bigint] NOT NULL,

[Used_MB] [numeric](36, 2) NULL,

[Unused_MB] [numeric](36, 2) NULL,

[Total_MB] [numeric](36, 2) NULL,

[Capture_Date] Date

)

SELECT @command = 'use [?]; 

SELECT Top 3

DB_Name(),s.Name AS SchemaName,

t.Name AS TableName,

p.rows AS RowCounts,

CAST(ROUND((SUM(a.used_pages) / 128.00), 2) AS NUMERIC(36, 2)) AS Used_MB,

CAST(ROUND((SUM(a.total_pages) - SUM(a.used_pages)) / 128.00, 2) AS NUMERIC(36, 2)) AS Unused_MB,

CAST(ROUND((SUM(a.total_pages) / 128.00), 2) AS NUMERIC(36, 2)) AS Total_MB,Getdate() As Capture_Date

FROM sys.tables t

INNER JOIN sys.indexes i ON t.OBJECT_ID = i.object_id

INNER JOIN sys.partitions p ON i.object_id = p.OBJECT_ID AND i.index_id = p.index_id

INNER JOIN sys.allocation_units a ON p.partition_id = a.container_id

INNER JOIN sys.schemas s ON t.schema_id = s.schema_id

GROUP BY t.Name, s.Name, p.Rows

ORDER BY CAST(ROUND((SUM(a.total_pages) / 128.00), 2) AS NUMERIC(36, 2)) desc' 

INSERT INTO @Max_Records   

EXEC sp_MSForEachDB @command     

--Select * from @Max_Records

SET @xml = CAST(( SELECT DB.DB_name As 'td',' ',DB.SchemaName AS 'td' ,' ',DB.TableName as 'td' ,' ',DB.RowCounts as 'td',' ',Db.Used_MB as 'td',  

' ',DB.Unused_MB as 'td' ,' ',DB.Total_MB as 'td',' ', convert(varchar(20), DB.Capture_Date,120) as 'td'  from @Max_Records  DB  Order by DB.RowCounts Desc

FOR XML PATH('tr'), ELEMENTS ) AS NVARCHAR(MAX))  

SET @body ='<html><body><H3>Top 3 Table Row count</H3>  

<table border = 1>   

<th> Database Name </th><th> Schema  Name </th> <th> TableName </th> <th> RowCounts</th> <th> Used_MB </th> <th> Unused_MB </th>  

<td bgcolor=#F0E68C><b>Total_MB(%)<b> </td> <th>Capture_Date</th></tr>'      

--<th> Server Name </th><th> Database Name </th> <th> PhysicalFileName </th> <th> FileSizeMB </th> <th> SpaceUsedMB </th> <th> FreeSpaceMB </th><th> FreeSpace(%) </th> <th>Capture_Date</th></tr>'      

SET @body = @body + @xml +'</table></body></html>'  

Set @cmd= @@SERVERNAME + ': Top 3 Table Row count '  

SELECT Top 1 @profile_name=name  FROM msdb.dbo.sysmail_profile  

EXEC msdb.dbo.sp_send_dbmail  

@profile_name = @profile_name, -- replace with your SQL Database Mail Profile   

@body = @body,  

@body_format ='HTML',  

@recipients = 'IT.ESA-DBA@sqldbanow.com', -- replace with your email address  

@subject = @cmd

Log_Backup-Status_report via Email alert in SQL Server

 Set nocount ON

Declare @DBName Varchar (500), @dbIs SQL_Variant, @dbStatus SQL_Variant,@replicaid Varchar(500),@cmd Varchar (1000),@profile_name Varchar(1000),@Bkupstatus Varchar (500)



If  OBJECT_ID('tempdb..#DBBackup') is not NULL

     Drop table tempdb..#DBBackup


If  OBJECT_ID('tempdb..#Log') is not NULL

     Drop table tempdb..#Log

     


Create Table #DBBackup (Server varchar(500),DB varchar(1000), Backup_Status varchar(1000))

Create Table #Log (Server varchar(500),DB varchar(1000),Last_Backup Datetime,Time_Since_Minute int,Backup_Size numeric,Compressed_Backup_Size Numeric)

DECLARE @xml NVARCHAR(MAX)

DECLARE @body NVARCHAR(MAX)


Declare cur CURSOR for Select Name from sys.databases where name not in ('tempdb') and state_desc='ONLINE' and recovery_model_desc='FULL'  order by Name

Open cur

fetch next from cur into @DBName

while @@fetch_status=0

     Begin

Select @dbIs=Databasepropertyex (@DBName,'Updateability'),@dbStatus=Databasepropertyex (@DBName,'Status')

Select @replicaid=replica_id from sys.databases where name=@DBName

If   @replicaid is NULL And @dbStatus='ONLINE' 

       Begin

    insert into #DBBackup Select Upper(@@SERVERNAME) "Server", Upper(@DBName) "Database", ''

       End  

  Else If (@dbIs='READ_WRITE' or @dbIs IS NULL ) And @dbStatus='ONLINE' AND @replicaid is Not NULL

         Begin

   insert into #DBBackup Select Upper(@@SERVERNAME) "Server", Upper(@DBName) "Database", ''

         End

   fetch next from cur into @DBName

      End

Close Cur

Deallocate Cur


insert into #Log

SELECT @@Servername 'Server', Database_Name, 

CONVERT( SmallDateTime , MAX(Backup_Finish_Date)) as Full_Last_Backup, 

DATEDIFF(d, MAX(Backup_Finish_Date), Getdate()) as Days_Since_Last,(Backup_Size/1048576) AS Backup_Size ,(Compressed_Backup_Size/1048576) AS Compressed_Backup_Size

FROM MSDB.dbo.BackupSet

WHERE Type = 'l' 

GROUP BY Database_Name,backup_size,compressed_backup_size

Having  DATEDIFF(MINUTE, MAX(Backup_Finish_Date), Getdate()) <5

order by 2 



Update #DBBackup

Set Backup_Status='FAILED'

where  DB not in (Select DB from #Log)


Update #DBBackup

Set Backup_Status='Completed'

where Backup_Status<>'FAILED'


--SET @xml = CAST(( SELECT DB.Server As 'td',' ',DB.DB AS 'td' ,'' ,DB.Backup_Status as 'td' ,'',L.Last_Backup as 'td','',L.Backup_Size as 'td',

--'',L.Compressed_Backup_Size as td from #DBBackup DB Left Outer join  #Log L on DB.DB=L.DB


--SELECT DB.Server As 'td',' ',DB.DB AS 'td' ,'' ,DB.Backup_Status as 'td' ,'',convert(varchar(20),L.Last_Backup,120) as 'td','',L.Backup_Size as 'td',

--'',L.Compressed_Backup_Size as td from #DBBackup DB Left Outer join  #Log L on DB.DB=L.DB where DB.Backup_Status='FAILED'

Select @Bkupstatus=Backup_Status from #DBBackup

If @Bkupstatus='FAILED'

Begin

SET @xml = CAST(( SELECT DB.Server As 'td',' ',DB.DB AS 'td' ,'' ,DB.Backup_Status as 'td' ,'',convert(varchar(20),L.Last_Backup,120) as 'td','',L.Backup_Size as 'td',

'',L.Compressed_Backup_Size as td from #DBBackup DB Left Outer join  #Log L on DB.DB=L.DB where DB.Backup_Status='FAILED'

     FOR XML PATH('tr'), ELEMENTS ) AS NVARCHAR(MAX))


SET @body ='<html><body><H3>Log Database Backup status </H3>

<table border = 1> 

<tr>

<th> Server Name </th> <th> Database Name </th> <th> Backup Status </th> <th> Last_Backup </th><th> Backup_Size (MB) </th>  <th> Compressed_Backup_Size (MB) </th> </tr>'    

--<td bgcolor=#F0E68C><b>FreeSpace(%)<b> </td> <th>Capture_Date</th></tr>' 

SET @body = @body + @xml +'</table></body></html>'

Set @cmd= @@SERVERNAME + ': Log Database Backup '

SELECT Top 1 @profile_name=name  FROM msdb.dbo.sysmail_profile

EXEC msdb.dbo.sp_send_dbmail

@profile_name = @profile_name, -- replace with your SQL Database Mail Profile 

@body = @body,

@body_format ='HTML',

@recipients = 'IT.ESA-DBA@sqldbanow.com', -- replace with your email address

@subject = @cmd

End

DROP TABLE [#DBBackup]

DROP TABLE [#Log]

Full Database Backup status report via email alert in SQL Server

 Set nocount ON

Declare @DBName Varchar (500), @dbIs SQL_Variant, @dbStatus SQL_Variant,@replicaid Varchar(500),@cmd Varchar (1000),@profile_name Varchar(1000)


If  OBJECT_ID('tempdb..#DBBackup') is not NULL

     Drop table tempdb..#DBBackup


If  OBJECT_ID('tempdb..#Log') is not NULL

     Drop table tempdb..#Log

     


Create Table #DBBackup (Server varchar(500),DB varchar(1000), Backup_Status varchar(1000))

Create Table #Log (Server varchar(500),DB varchar(1000),Last_Backup Date,Time_Since_Minute int,Backup_Size numeric,Compressed_Backup_Size Numeric)

DECLARE @xml NVARCHAR(MAX)

DECLARE @body NVARCHAR(MAX)


Declare cur CURSOR for Select Name from sys.databases where name not in ('tempdb') and state_desc='ONLINE' order by Name

Open cur

fetch next from cur into @DBName

while @@fetch_status=0

     Begin

Select @dbIs=Databasepropertyex (@DBName,'Updateability'),@dbStatus=Databasepropertyex (@DBName,'Status')

Select @replicaid=replica_id from sys.databases where name=@DBName

If   @replicaid is NULL And @dbStatus='ONLINE' 

       Begin

    insert into #DBBackup Select Upper(@@SERVERNAME) Server, Upper(@DBName) Database, ''

       End  

  Else If (@dbIs='READ_WRITE' or @dbIs IS NULL ) And @dbStatus='ONLINE' AND @replicaid is Not NULL

         Begin

   insert into #DBBackup Select Upper(@@SERVERNAME) Server, Upper(@DBName) Database, ''

         End

   fetch next from cur into @DBName

      End

Close Cur

Deallocate Cur


insert into #Log

SELECT @@Servername 'Server', Database_Name, 

CONVERT( SmallDateTime , MAX(Backup_Finish_Date)) as Full_Last_Backup, 

DATEDIFF(d, MAX(Backup_Finish_Date), Getdate()) as Days_Since_Last,(Backup_Size1048576) AS Backup_Size ,(Compressed_Backup_Size1048576) AS Compressed_Backup_Size

FROM MSDB.dbo.BackupSet

WHERE Type = 'd' 

GROUP BY Database_Name,backup_size,compressed_backup_size

Having  DATEDIFF(MINUTE, MAX(Backup_Finish_Date), Getdate()) 120

order by 2 



Update #DBBackup

Set Backup_Status='FAILED'

where  DB not in (Select DB from #Log)


Update #DBBackup

Set Backup_Status='Completed'

where Backup_Status'FAILED'


SET @xml = CAST(( SELECT DB.Server As 'td',' ',DB.DB AS 'td' ,'' ,DB.Backup_Status as 'td' ,'',L.Last_Backup as 'td','',L.Backup_Size as 'td',

'',L.Compressed_Backup_Size as td from #DBBackup DB Left Outer join  #Log L on DB.DB=L.DB

                    FOR XML PATH('tr'), ELEMENTS ) AS NVARCHAR(MAX))


SET @body ='htmlbodyH3Full Database Backup status H3

table border = 1 

tr

th Server Name th th Database Name th th Backup Status th th Last_Backup th th Backup_Size (MB) th th Compressed_Backup_Size (MB) th tr'    

 

SET @body = @body + @xml +'tablebodyhtml'


Set @cmd= @@SERVERNAME + ' Full Database Backup '


SELECT Top 1 @profile_name=name  FROM msdb.dbo.sysmail_profile


EXEC msdb.dbo.sp_send_dbmail

@profile_name = @profile_name, -- replace with your SQL Database Mail Profile 

@body = @body,

@body_format ='HTML',

@recipients = 'itesadba@sqldbanow.com', -- replace with your email address

@subject = @cmd


DROP TABLE [#DBBackup]

DROP TABLE [#Log]

Database Index Status report in SQL Server via email alert

 DECLARE @command VARCHAR(5000),@cmd Varchar (1000),@profile_name Varchar(1000)  

DECLARE @xml NVARCHAR(MAX)  

DECLARE @body NVARCHAR(MAX)  


DECLARE @Index_details TABLE (

 Database_name sysname,

 Objectname sysname,

 Objectid Int,

 Indexid Int,

 partitionnum Int,

 frag decimal(30,2),

 Page_Count Int,

 Capture_Date Date)


Insert Into @Index_details

EXEC sp_MSForEachDB

'use [?]; SELECT DB_Name() As Database_name,Object_name (OBJECT_ID) As Object_name, [object_id] AS objectid ,index_id AS indexid,partition_number AS partitionnum,avg_fragmentation_in_percent AS frag, page_count,getdate()

FROM sys.dm_db_index_physical_stats (DB_ID(), NULL, NULL , NULL, ''LIMITED'')

WHERE avg_fragmentation_in_percent > 10.0  -- Allow limited fragmentation

AND index_id > 0 -- Ignore heaps

AND page_count > 25 -- Ignore small tables

Order by avg_fragmentation_in_percent Desc,page_count Desc'


--Select * from @Index_details



SET @xml = CAST(( SELECT ID.Database_name As 'td',' ',ID.Objectname AS 'td' ,' ',ID.Objectid as 'td' ,' ',ID.Indexid 'td',' ',ID.partitionnum as 'td',  

' ',ID.frag as 'td' ,' ',ID.Page_Count as 'td',' ', convert(varchar(20), ID.Capture_Date,120) as 'td'  from @Index_details  ID  

FOR XML PATH('tr'), ELEMENTS ) AS NVARCHAR(MAX))  


SET @body ='<html><body><H3>Database Index Status </H3>  

<table border = 1>   

<th> Database Name </th><th> Objectname </th> <th> Objectid </th> <th> Indexid </th> <th> Partition </th> <th> frag </th>  

<td bgcolor=#F0E68C><b>Pagecount<b> </td> <th>Capture_Date</th></tr>'      

--<th> Server Name </th><th> Database Name </th> <th> PhysicalFileName </th> <th> FileSizeMB </th> <th> SpaceUsedMB </th> <th> FreeSpaceMB </th><th> FreeSpace(%) </th> <th>Capture_Date</th></tr>'      

SET @body = @body + @xml +'</table></body></html>'  

Set @cmd= @@SERVERNAME + ': Database Index Status '  

SELECT Top 1 @profile_name=name  FROM msdb.dbo.sysmail_profile  


EXEC msdb.dbo.sp_send_dbmail  

@profile_name = @profile_name, -- replace with your SQL Database Mail Profile   

@body = @body,  

@body_format ='HTML',  

@recipients =  'IT.ESA-DBA@sqldbanow.com', -- replace with your email address  

@subject = @cmd

Current Disk Free Space in SQL Server via email alert

 DECLARE @cmd Varchar (1000),@profile_name Varchar(1000)  

DECLARE @xml NVARCHAR(MAX)  

DECLARE @body NVARCHAR(MAX)  


Declare @Disk_Size Table

(Drive Nvarchar(Max),Free_Space_MB decimal(30,2))

Insert Into @Disk_Size

Exec Xp_fixeddrives


--Select * from @Disk_Size


SET @xml = CAST(( SELECT DS.Drive As 'td',' ',DS.Free_Space_MB AS 'td' ,' ', convert(varchar(20),getdate(),120) as 'td'  from @Disk_Size  DS  

FOR XML PATH('tr'), ELEMENTS ) AS NVARCHAR(MAX))


SET @body ='<html><body><H3>Current Disk Free Space </H3>  

<table border = 1>   

<th> Drive Name </th><td bgcolor=#F0E68C><b>Free_Space_MB (%)<b> </td> <th>Capture_Date</th></tr>'      

--<th> Server Name </th><th> Database Name </th> <th> PhysicalFileName </th> <th> FileSizeMB </th> <th> SpaceUsedMB </th> <th> FreeSpaceMB </th><th> FreeSpace(%) </th> <th>Capture_Date</th></tr>'      

SET @body = @body + @xml +'</table></body></html>'  

Set @cmd= @@SERVERNAME + ': Current Disk Free Space'  

SELECT Top 1 @profile_name=name  FROM msdb.dbo.sysmail_profile  


EXEC msdb.dbo.sp_send_dbmail  

@profile_name = @profile_name, -- replace with your SQL Database Mail Profile   

@body = @body,  

@body_format ='HTML',  

@recipients = 'IT.ESA-DBA@sqldbanow.com', -- replace with your email address  

@subject = @cmd

Backup Status Report in SQL Server via Email

 Set nocount ON

Declare @DBName Varchar (500), @dbIs SQL_Variant, @dbStatus SQL_Variant,@replicaid Varchar(500)

Declare @cmd Varchar (1000),@profile_name Varchar(1000), @description Varchar (500)


If  OBJECT_ID('tempdb..#DBBackup') is not NULL

     Drop table tempdb..#DBBackup


If  OBJECT_ID('tempdb..#DBBackup') is not NULL

     Drop table tempdb..#FullBackup


If  OBJECT_ID('tempdb..#DBBackup') is not NULL

     Drop table tempdb..#DiffBackup


If  OBJECT_ID('tempdb..#Log') is not NULL

     Drop table tempdb..#Log

     


Create Table #DBBackup (Server varchar(500),DB varchar(1000),Full_Backup_Status varchar(1000),Diff_Backup_Status varchar(1000), Log_Backup_Status varchar(1000))

Create Table #FullBackup (Server varchar(500),DB varchar(1000),Full_Last_Backup Datetime,Time_Since_Minute int,Backup_Size numeric,Compressed_Backup_Size Numeric)

Create Table #DiffBackup (Server varchar(500),DB varchar(1000),Diff_Last_Backup Datetime,Time_Since_Minute int,Backup_Size numeric,Compressed_Backup_Size Numeric)

Create Table #Log (Server varchar(500),DB varchar(1000),Log_Last_Backup Datetime,Time_Since_Minute int,Backup_Size numeric,Compressed_Backup_Size Numeric)

DECLARE @xml NVARCHAR(MAX)

DECLARE @body NVARCHAR(MAX)


Declare cur CURSOR for Select Name from sys.databases where name not in ('tempdb') and state_desc='ONLINE' and recovery_model_desc='FULL'  order by Name

Open cur

fetch next from cur into @DBName

while @@fetch_status=0

     Begin

Select @dbIs=Databasepropertyex (@DBName,'Updateability'),@dbStatus=Databasepropertyex (@DBName,'Status')

Select @replicaid=replica_id from sys.databases where name=@DBName

Set @description= ''

SELECT @description =  hars.role_desc

FROM sys.DATABASES d

INNER JOIN sys.dm_hadr_availability_replica_states hars ON d.replica_id = hars.replica_id

WHERE database_id = DB_ID(@DBName)

   

    if (@description<>'SECONDARY' and @dbIs='READ_WRITE')

    Begin

    insert into #DBBackup Select Upper(@@SERVERNAME) "Server", Upper(@DBName) "Database", '','',''

    End  

fetch next from cur into @DBName

  End

Close Cur

Deallocate Cur


--Full backup Status--

If Datename(weekday,(getdate()))='Monday'

   Begin

insert into #FullBackup

SELECT @@Servername 'Server', Database_Name, 

CONVERT( SmallDateTime , MAX(Backup_Finish_Date)) as Full_Last_Backup, 

DATEDIFF(d, MAX(Backup_Finish_Date), Getdate()) as Days_Since_Last,(Backup_Size/1048576) AS Backup_Size ,(Compressed_Backup_Size/1048576) AS Compressed_Backup_Size

FROM MSDB.dbo.BackupSet

WHERE Type = 'd'  and is_copy_only=0

GROUP BY Database_Name,backup_size,compressed_backup_size

Having  DATEDIFF(MINUTE, MAX(Backup_Finish_Date), Getdate()) <360

order by 2 

  End

else

   Begin

insert into #FullBackup

SELECT @@Servername 'Server', Database_Name, 

CONVERT( SmallDateTime , MAX(Backup_Finish_Date)) as Full_Last_Backup, 

DATEDIFF(d, MAX(Backup_Finish_Date), Getdate()) as Days_Since_Last,(Backup_Size/1048576) AS Backup_Size ,(Compressed_Backup_Size/1048576) AS Compressed_Backup_Size

FROM MSDB.dbo.BackupSet

WHERE Type = 'd'  and is_copy_only=0

GROUP BY Database_Name,backup_size,compressed_backup_size

Having  DATEDIFF(Day, MAX(Backup_Finish_Date), Getdate()) <8

order by 2 

End

Update #DBBackup

Set Full_Backup_Status='**Need to backup verify**'

where  DB not in (Select DB from #FullBackup)


Update #DBBackup

Set Full_Backup_Status='Completed'

where Full_Backup_Status<>'**Need to backup verify**'


--Select * from #DBBackup


--Diff Backup Satatus -----

If Datename(weekday,(getdate()))='Monday'

   Begin

insert into #DiffBackup

SELECT @@Servername 'Server', Database_Name, 

CONVERT( SmallDateTime , MAX(Backup_Finish_Date)) as Full_Last_Backup, 

DATEDIFF(d, MAX(Backup_Finish_Date), Getdate()) as Days_Since_Last,(Backup_Size/1048576) AS Backup_Size ,(Compressed_Backup_Size/1048576) AS Compressed_Backup_Size

FROM MSDB.dbo.BackupSet

WHERE Type = 'I' 

GROUP BY Database_Name,backup_size,compressed_backup_size

Having  DATEDIFF(DAY, MAX(Backup_Finish_Date), Getdate()) <3

order by 2 

    End

 Else

     Begin   

    insert into #DiffBackup

SELECT @@Servername 'Server', Database_Name, 

CONVERT( SmallDateTime , MAX(Backup_Finish_Date)) as Full_Last_Backup, 

DATEDIFF(d, MAX(Backup_Finish_Date), Getdate()) as Days_Since_Last,(Backup_Size/1048576) AS Backup_Size ,(Compressed_Backup_Size/1048576) AS Compressed_Backup_Size

FROM MSDB.dbo.BackupSet

WHERE Type = 'I' 

GROUP BY Database_Name,backup_size,compressed_backup_size

Having  DATEDIFF(MINUTE, MAX(Backup_Finish_Date), Getdate()) <180

order by 2 

      End



Update #DBBackup

Set Diff_Backup_Status='**Need to backup verify**'

where  DB not in (Select DB from #DiffBackup)


Update #DBBackup

Set Diff_Backup_Status='Completed'

where Diff_Backup_Status<>'**Need to backup verify**'



SET @xml = CAST(( SELECT DB.Server As 'td',' ',DB.DB AS 'td' ,'' ,DB.Full_Backup_Status as 'td' ,'',convert(varchar(20),F.Full_Last_Backup,120) as 'td','',

Diff_Backup_Status as 'td','',convert(varchar(20),D.Diff_Last_Backup,120) as td 

from #DBBackup DB Left Outer join #FullBackup F on DB.DB=F.DB  Left outer join #DiffBackup D on DB.DB=D.DB

                    FOR XML PATH('tr'), ELEMENTS ) AS NVARCHAR(MAX))


SET @body ='<html><body><H3> Database Backup status </H3>

<table border = 1> 

<tr>

<th> Server Name </th> <th> Database Name </th> <th> Full_Backup_Status </th> <th> Full_Last_Backup </th><th> Differential_Backup_Status </th><th> Differential_Last_Backup</th> </tr>'    

 --<td bgcolor=#F0E68C><b>FreeSpace(%)<b> </td> <th>Capture_Date</th></tr>' 


SET @body = @body + @xml +'</table></body></html>'


Set @cmd= @@SERVERNAME + ': Database Backup Status'


SELECT Top 1 @profile_name=name  FROM msdb.dbo.sysmail_profile


EXEC msdb.dbo.sp_send_dbmail

@profile_name = @profile_name, -- replace with your SQL Database Mail Profile 

@body = @body,

@body_format ='HTML',

@recipients =  'itesadba@sqldbanow.com', -- replace with your email address

@subject = @cmd


DROP TABLE [#DBBackup]

DROP TABLE [#FullBackup]

DROP TABLE [#DiffBackup]

DROP TABLE [#Log]

AG Status Report in SQL

 Declare @cmd Varchar (1000),@profile_name Varchar(1000), @description Varchar (500)

DECLARE @xml NVARCHAR(MAX), @body NVARCHAR(MAX)

SET @xml = CAST(( SELECT @@Servername As 'td',' ',Name AS 'td' ,'' ,role_desc as 'td' ,'',operational_state_desc as 'td'

from Sys.availability_groups_cluster AS AGC  Inner Join Sys.dm_hadr_availability_replica_cluster_states As RCS

on RCS.group_id=AGC.group_id Inner Join Sys.dm_hadr_availability_replica_states As ARS on ARS.replica_id=RCS.replica_id

Inner Join Sys.availability_group_listeners AS AGL

ON AGL.group_id=ARS.group_id

Where operational_state_desc is not NULL

order by 3  FOR XML PATH('tr'), ELEMENTS ) AS NVARCHAR(MAX))

SET @body ='<html><body><H3> Availability Groups status </H3>

<table border = 1> 

<tr>

<th> Server Name </th> <th> Availability Groups </th> <th> Role </th> <th>Status </th> </tr>'    


SET @body = @body + @xml +'</table></body></html>'


Set @cmd= @@SERVERNAME + ': Availability Groups status'


SELECT Top 1 @profile_name=name  FROM msdb.dbo.sysmail_profile


EXEC msdb.dbo.sp_send_dbmail

@profile_name = @profile_name, -- replace with your SQL Database Mail Profile 

@body = @body,

@body_format ='HTML',

--@recipients =  'ajeyudu@sqldbanow.com', -- replace with your email address

@recipients =  'IT.ESA-DBA@sqldbanow.com', -- replace with your email address

@subject = @cmd

Troubleshooting master database corrupted in SQL Server

 One of an instance master database data file was corrupted and I was unable to start the server. How to troubleshoot this scenario?

Possible Scenarios

If the master files are corrupted or damaged, instance cannot be started. We have to rebuild master database then by running the server in single user mode we have to restore latest backup to get previous settings.

Steps

1.      Check the error log for exact reason.

2.      Rebuild master database as follows by running setup from

C:\Program Files\Microsoft SQL Server\100\Setup Bootstrap\Release

For windows authentication:

setup /ACTION=REBUILDDATABASE /QUIET /INSTANCENAME=<instance
name> /SQLSYSADMINACCOUNTS=<accounts>

 

For mixed mode:

setup /ACTION=REBUILDDATABASE /QUIET /INSTANCENAME=<instance
name> /SQLSYSADMINACCOUNTS=<accounts> /SAPWD=password

3.      Once rebuilding is completed then run the server in single user mode

4.   Restore master database by replacing existing one.

Restart the server in multi user mode.

Troubleshooting host name changes in SQL Server

 When the machine name is changed where we have installed SQL Server, all the instances services are started but replication, Jobs, Alerts, Maintenance plans causes errors. Hence we have to rename the instance.

To rename instance we can use the following SP

Steps:

1.      Check the old server name as follows

SELECT @@servername

2.      Drop the server and add the new server name

             SP_DROPSERVER   <oldName>

           SP_ADDSERVER <newName>, local

3.      Restart the instance

4.      Check the server name again

SELECT @@servername

How to apply patches in SQL Server SQL Cluster Environment:

 SQL Cluster Environment:

Apply a SQL Service Pack or hot-fix in a 2 node Active/Passive SQL Cluster environment.

Active SQL Server: SQLDBANOWDBALABS

Passive SQL Server: SQLDBANOWDBALABS-DR

1. First apply the SQL Service Pack on Passive Server. (SQLDBANOWDBALABS-DR)

2. Post SP/hot-fix installation completion, restart the Passive Server if prompted.

3. Failover the SQL Cluster Service/Instance from Active to Passive Server.

Post Failover:

New Active Server: SQLDBANOWDBALABS-DR

New Passive Server: SQLDBANOWDBALABS

4. Now apply the SQL Service pack on New Passive Server. (SQLDBANOWDBALABS)

5. Post SP/hot-fix installation completion, restart the New Passive Server if prompted.

6. Failback the SQL Cluster Service/Instance from Active to Passive Server.

Post Failback:

Active Server: SQLDBANOWDBALABS

Passive Server: SQLDBANOWDBALABS-DR

7. Finally verify the SQL Cluster Services and Cluster Disk Health Check in Failover Cluster Manager.

How to apply patches in SQL Server Always On Environment

 SQL Always On Environment:

Apply a SQL Service Pack or hot-fix in SQL Server Always-On environment.

Primary SQL Replica: SQLDBANOWDBALABS

Secondary SQL Replica: SQLDBANOWDBALABS-DR

Apply SP/Hot-fix on all Secondary AG Replica's 

Finally Apply SP/Hot-fix on Primary AG Replica.

1. On Secondary AG Replica: (SQLDBANOWDBALABS-DR)

Ensure AG Databases are in Synchronized Status.

Apply the SQL Service Pack on Secondary Replica Server. (SQLDBANOWDBALABS-DR)

Post SP/hot-fix installation completion, restart the Secondary Replica Server if prompted.

2. On Primary AG Replica: (SQLDBANOWDBALABS)

Failover the SQL AG Group from Primary Replica to Secondary Replica.

3. Post AG Group Failover:

New Primary Replica : SQLDBANOWDBALABS-DR

New Secondary Replica: SQLDBANOWDBALABS

4. On New Secondary AG Replica: (SQLDBANOWDBALABS)

Apply the SQL Service pack on New Secondary Replica Server. (SQLDBANOWDBALABS)

Post SP/hot-fix installation completion, restart the New Secondary Replica Server if prompted.

5. On New Primary AG Replica: (SQLDBANOWDBALABS-DR)

Failback the SQL AG Group from Primary to Secondary Replica.

6. Post AG Group Failback:

Primary Replica : SQLDBANOWDBALABS

Secondary Replica: SQLDBANOWDBALABS-DR

7. Finally verify the SQL AG Group Health Check in AG DashBoard Reports.

Step by Step Process for DB Migration in SQL Server

 

Step by Step Process for DB Migration (Side by Side)

Step 1: Once the Target VM is ready, we need to install the SQL Version based on the recommendations or SOP.

Step 2: Take a backup from the Source and Copy to the Target and restore with Recovery option

Step 3: Move all the logins (by using sp_help_revlogin), Jobs, Operators, DB Mail Configurations and Server Configurations

Step 4: Move all the linked servers and if any Proxy accounts

Step 5: Enable inbound/outbound firewall rules for SQL Server/Agent Service and Browser Service

Step 6: Handover the Server to Test their application

Step 7: Once Application team confirmed, everything looks good then will align with all the stake holders/application team and Business Users and required teams and finalize the cutover date for actual migration

On the Day of Cutover, follow the below steps

Step 1: Inform to Application team to bring down the app services

Step 2: Disable if any backup policies enabled from the Third-Party Tools like EMC, NETWORKER or Veeam or Commvault

Step 3: Disable the Backup account if any

Step 4: Initiate Full backups for all the databases to Native Drive or Shared Location, Keep the backup file name in Standard Format like ServerName_DB_Name_Type_Date.bak\trn

Step 5: Connect to the target server and map the shared location or copy the backup files from the folder

Step 6: Restore the databases with No Recovery if it is a production, because if we want to take a log backup from source and then copy those t-log backups to target server and restore with recovery option

Step 7: Once log backups are restored, verify all the databases are online or not, if not take necessary action

Step 8: Fix Orphan Users by funding the sp_change_users_login ‘Report’

Step 9: Verify the Linked Servers Connections

Step 10: Verify the DB Owner Data details and change if needed and change the compatibility

Step 11: Verify the Job owner details and take necessary action if required

Step 12: Handover to the Application for Validation

Once DB Activities are completed, App team will modify their connection strings and Network team will make the ns changes and update to app team to validate

Step 13: App team will validate and confirm whether application is working or not. If any login issues troubleshoot and fix

 

POA(Plan of Action) for Database Migration in SQL Server

Pre Migration Checklist
Sr.No.
1 Analyze the disk space of the target server for the new database.
2 Confirm the data and log file location for the target server.
3 Collect the information about the Database properties (Auto Stats, DB Owner, Recovery Model, Compatibility level,etc).
4 Collect the information of dependent applications, make sure application services will be stopped during the database migration.
5 Collect the information of database logins, users and their permissions.
6 Check the database for the Orphan users if any.
7 Check the SQL Server for any dependent objects (SQL Agent Jobs and Linked Servers).
8 Check, if the database is part of any maintenance plan.
Database Migration Checklist
Sr.No.
1 Stop the application services.
2 Change the database to single user mode.
3 Take the latest backup of all the databases involved in migration.
4 Stop the SQL Services on live server.
5 Copy the backup from live to destination server.
6 Restore the databases on the target server on the appropriate drives.
7 Cross check the database properties as per pre-migration checklist output.
8 Execute the output of Login transfer script on the target server, to create logins on the target server.
9 Check for Orphan Users and Fix Orphan Users. 
10 Execute DBCC UPDATEUSAGE on the restored database.
11 Rebuild Indexes ,As per the requirement.
12 Update statistics.
13 Recompile procedures.
14 Configure Full backup, Log backup, integrity check, rebuild index jobs.
Post Migration Checlklist
Sr.No.
1 Check the integrity of database.
2 Start the application services, check the application functionality.
3 Check the SQL Server Error Log for login failures and other errors.

ISSUE 4: FIND OUT TABLE & INDEX SIZE

Create the temp table for further querying

CREATE TABLE #temp (

            rec_id               int IDENTITY (1, 1),

            table_name      varchar(128),

            nbr_of_rows    int,

            data_space      decimal(15,2),

            index_space     decimal(15,2),

            total_size         decimal(15,2),

            percent_of_db decimal(15,12),

            db_size            decimal(15,2))

 

2.      Get all tables, names, and sizes

EXEC sp_msforeachtable @command1="insert into #temp (no_of_rows, data_space, index_space) exec sp_mstablespace '?'", @command2="update #temp set table_name = '?' where rec_id = (select max(rec_id) from #temp)"

3.      Set the total_size and total database size fields

UPDATE #temp SET total_size = (data_space + index_space), db_size = (SELECT SUM(data_space + index_space) FROM #temp)

4.      Set the percent of the total database size

UPDATE #temp SET percent_of_db = (total_size/db_size) * 100

5.       Get the data

SELECT *FROM #temp ORDER BY total_size DESC

6.       Comment out the following line if you want to do further querying

DROP TABLE #temp

ISSUE 3: SHRINKDATABASE (DIFFERENT PROCESS)

If you ever want to transfer a large DB to a new one with more than one file, here is the way I am going to use (tested and approved)

1. Create a file which is as large as the data in your primary file (call it "buffer")

2. Empty the primary file (DBCC SHRINKFILE (<FILENAME>, EMPTYFILE))

3. Restart SQL Server Engine

4. Shrink the primary file to the Data size divided by the number of files you're gonna create (DBCC SHRINKFILE (<FILENAME>, NEWSIZE))

5. Create all the new files with the size of data divided by the number of files

6. Restrict their growth in order to fill the primary file in the next operation

7. Empty the buffer file (DBCC SHRINKFILE (BUFFER, EMPTYFILE))

8. Delete the buffer file (ALTER DATABASE REMOVE FILE (NAME=BUFFER))

9. Set final size of data files and unrestrict their growth according to the final configuration needed

ISSUE 2: MOVING MASTER DATABASE

 

1. Create two folders and grant read write permissions to service account

            d:\master_data

            e:\master_log

2. Find the current path

            sp_helpdb   master

3. Stop SQL Server

4. Move the files (master.mdf, mastlog.ldf) into new folders

5.  Go to SSCM --> R.C on respective instance SQL Server Service -- properties -->   Advanced --> Startup Parameters--> Change the    path of data and Log file

            -dd:\master_data\master.mdf;-e....

            -le:\master_log\mastlog.ldf

6. Apply --> OK

7. Start the service. Go to SSMS --> check the new path

            sp_helpdb master