To Get Report of DDL Changes
automation #automation
DECLARE @HTMLTablecount NVARCHAR(MAX);
DECLARE @HTMLtable NVARCHAR(MAX);
DECLARE @HTMLDeletedTables NVARCHAR(MAX);
DECLARE @HTMLNewColumns NVARCHAR(MAX);
DECLARE @HTMLDataTypeChange NVARCHAR(MAX);
DECLARE @HTMLDataTypeSizeChange NVARCHAR(MAX);
DECLARE @EmailBody NVARCHAR(MAX);
-- HTML for New Tables Created
SET @HTMLtable =
N'<H5 style="color: #3dab15; font-family: Arial, Verdana">New Tables Created Report</H5>' +
N'<table border="3" style="font-family: Arial, Verdana; text-align:left; font-size:9pt; color: #000033; width: auto;">' +
N'<tr style="text-align: left;">
<th style="text-align:left;background-color: #FFA500; color:#FFF; font-weight: bold; width: auto;">New Tables Created</th>
</tr>' +
CAST((
SELECT
Currents.TableName AS 'td'
FROM (SELECT table_name AS TableName
FROM information_schema.tables
WHERE table_type = 'BASE TABLE') AS Currents
LEFT JOIN
TableStructureSnapshot AS Snapshots
ON
Currents.TableName = Snapshots.TableName
WHERE
Snapshots.TableName IS NULL
FOR XML PATH('tr'), TYPE
) AS NVARCHAR(MAX) ) +
N'</table>';
-- HTML for New Tables Count
SET @HTMLTablecount =
N'<H5 style="color: #3dab15; font-family: Arial, Verdana">Total Count of Tables</H5>'+
N'<table border="3" style="font-family: Arial, Verdana; text-align:left; font-size:9pt; width: auto; color: #000033">' +
N'<tr style="text-align: left;">
<th style="text-align:left;background-color: #FFA500; color:#FFF; font-weight: bold; width: 25%;">New Tables Count</th>
</tr>' +
CAST((
SELECT
COUNT(*) AS 'td'
FROM information_schema.tables
FOR XML PATH('tr'), TYPE
) AS NVARCHAR(MAX) ) +
N'</table>';
-- HTML for Missing Tables
SET @HTMLDeletedTables =
N'<H5 style="color: #3dab15; font-family: Arial, Verdana">Missing Tables Report</H5>' +
N'<table border="3" style="font-family: Arial, Verdana; text-align:left; font-size:9pt; color: #000033">' +
N'<tr style="text-align: left;">
<th style="text-align:left;background-color: #FFA500; color:#FFF; font-weight: bold; width: 25%;">Missing Tables</th>
</tr>' +
CAST((
SELECT
DISTINCT
Snapshots.TableName, ''
FROM
TableStructureSnapshot AS Snapshots
LEFT JOIN information_schema.tables AS Currents
ON
Snapshots.TableName = Currents.table_name
WHERE
Currents.table_name IS NULL
FOR XML PATH('tr'), TYPE
) AS NVARCHAR(MAX) ) +
N'</table>';
-- Create a temporary table for column comparison results
IF OBJECT_ID('tempdb.#ComparisonResults') IS NOT NULL
DROP TABLE #ComparisonResults;
CREATE TABLE #ComparisonResults (
TableName NVARCHAR(255),
ColumnName NVARCHAR(255),
DataType NVARCHAR(255),
IsNullable NVARCHAR(3)
);
-- Insert comparison results into the temporary table
INSERT INTO #ComparisonResults (TableName, ColumnName, DataType, IsNullable)
SELECT curr.TableName,
curr.ColumnName,
curr.DataType,
curr.IsNullable
FROM (SELECT table_name AS TableName, column_name AS ColumnName, data_type AS DataType, is_nullable AS IsNullable
FROM information_schema.columns) AS curr
FULL OUTER JOIN
TableStructureSnapshot AS snap
ON curr.TableName = snap.TableName
AND curr.ColumnName = snap.ColumnName
WHERE curr.TableName IS NULL
OR snap.TableName IS NULL
OR curr.ColumnName IS NULL
OR snap.ColumnName IS NULL
OR curr.DataType <> snap.DataType
OR curr.IsNullable <> snap.IsNullable;
-- Generate HTML for New Columns Detected
SET @HTMLNewColumns =
N'<H5 style="color: #3dab15; font-family: Arial, Verdana">New Columns Detected</H5>' +
N'<table border="3" style="font-family: Arial, Verdana; text-align:left; font-size:9pt; color: #000033">' +
N'<tr style="text-align: left;">
<th style="text-align:left;background-color: #FFA500; color:#FFF; font-weight: bold; width: 25%;">TableName</th>
<th style="text-align:left;background-color: #FFA500; color:#FFF; font-weight: bold; width: 25%;">ColumnName</th>
<th style="text-align:left;background-color: #FFA500; color:#FFF; font-weight: bold; width: 25%;">DataType</th>
<th style="text-align:left;background-color: #FFA500; color:#FFF; font-weight: bold; width: 25%;">IsNullable</th>
</tr>' +
CAST((
SELECT
TableName AS 'TD',
ColumnName AS 'TD',
DataType AS 'TD',
IsNullable AS 'TD'
FROM
#ComparisonResults
WHERE
TableName IS NOT NULL
FOR XML PATH('tr'), TYPE
) AS NVARCHAR(MAX) ) +
N'</table>';
-- HTML for Datatype Changes
SET @HTMLDataTypeChange =
N'<H5 style="color: #3dab15; font-family: Arial, Verdana">Datatype Changes Detected</H5>' +
N'<table border="3" style="font-family: Arial, Verdana; text-align:left; font-size:9pt; color: #000033">' +
N'<tr style="text-align: left;">
<th style="text-align:left;background-color: #FFA500; color:#FFF; font-weight: bold; width: 25%;">TableName</th>
<th style="text-align:left;background-color: #FFA500; color:#FFF; font-weight: bold; width: 25%;">ColumnName</th>
<th style="text-align:left;background-color: #FFA500; color:#FFF; font-weight: bold; width: 25%;">OldDataType</th>
<th style="text-align:left;background-color: #FFA500; color:#FFF; font-weight: bold; width: 25%;">NewDataType</th>
</tr>' +
CAST((
SELECT tss.TableName AS 'TD',
tss.ColumnName AS 'TD',
tss.OldDataType AS 'TD',
tss.NewDataType AS 'TD'
FROM (SELECT tss.TableName,
tss.ColumnName,
tss.DataType AS OldDataType,
ic.DATA_TYPE AS NewDataType
FROM
TableStructureSnapshot tss
JOIN information_schema.columns ic
ON tss.TableName = ic.TABLE_NAME
AND tss.ColumnName = ic.COLUMN_NAME
JOIN information_schema.tables it
ON it.TABLE_NAME = tss.TableName
WHERE tss.DataType <> ic.DATA_TYPE
AND it.TABLE_TYPE = 'BASE TABLE'
) AS tss
FOR XML PATH('tr'), TYPE
) AS NVARCHAR(MAX) ) +
N'</table>';
-- HTML for Datatype Size Changes
SET @HTMLDataTypeSizeChange =
N'<H5 style="color: #3dab15; font-family: Arial, Verdana">Datatype Size Changes Detected</H5>' +
N'<table border="3" style="font-family: Arial, Verdana; text-align:left; font-size:9pt; color: #000033">' +
N'<tr style="text-align: left;">
<th style="text-align:left;background-color: #FFA500; color:#FFF; font-weight: bold; width: 25%;">TableName</th>
<th style="text-align:left;background-color: #FFA500; color:#FFF; font-weight: bold; width: 25%;">ColumnName</th>
<th style="text-align:left;background-color: #FFA500; color:#FFF; font-weight: bold; width: 25%;">OldMaxLength</th>
<th style="text-align:left;background-color: #FFA500; color:#FFF; font-weight: bold; width: 25%;">NewMaxLength</th>
</tr>' +
CAST((
SELECT tss.TableName AS 'TD',
tss.ColumnName AS 'TD',
tss.OldMaxLength AS 'TD',
tss.NewMaxLength AS 'TD'
FROM (SELECT tss.TableName,
tss.ColumnName,
tss.CHARACTER_MAXIMUM_LENGTH AS OldMaxLength,
ic.CHARACTER_MAXIMUM_LENGTH AS NewMaxLength
FROM
TableStructureSnapshot tss
JOIN information_schema.columns ic
ON tss.TableName = ic.TABLE_NAME
AND tss.ColumnName = ic.COLUMN_NAME
JOIN information_schema.tables it
ON it.TABLE_NAME = tss.TableName
WHERE tss.CHARACTER_MAXIMUM_LENGTH <> ic.CHARACTER_MAXIMUM_LENGTH
AND it.TABLE_TYPE = 'BASE TABLE'
) AS tss
FOR XML PATH('tr'), TYPE
) AS NVARCHAR(MAX) ) +
N'</table>';
-- Combine all sections into a single email body
SET @EmailBody = @HTMLTablecount + N'<br/><br/>' + @HTMLtable + N'<br/><br/>' + @HTMLDeletedTables + N'<br/><br/>' + @HTMLNewColumns + N'<br/><br/>' + @HTMLDataTypeChange + N'<br/><br/>' + @HTMLDataTypeSizeChange;
-- Send email with the combined HTML body
EXEC msdb.dbo.sp_send_dbmail
@profile_name = 'your_db_mail_profile',
@recipients = 'your_email@example.com',
@body = @EmailBody,
@body_format = 'HTML',
@subject = 'Database Health Report';
-- Optionally, drop the temporary table when done
IF OBJECT_ID('tempdb.#ComparisonResults') IS NOT NULL
DROP TABLE #ComparisonResults;