Multiple IF EXISTS statement - html

I have a stored procedure that sends daily report for 2 operational machines. I also show on report misfire count per machine but if 1 machine has 0 misfires and the other has more than 0 the Misfire report section will be skipped and not reported.
First I want to check and see if any items exist for specific day and if not send report saying "No results found" or whatever, if they do exist then check to see if any misfires exist on both machines. I want to attach only the stats from the machine that has more than 0 and skip misfire report altogether if they both have 0. I will show what a report looks like that shows Daily Stats that has misfires on both machines.
If say TILT_1 reports 0 misfires and say TILT_2 reports 20 misfires on DAILY SORTER STATS portion then both TILT_1 and TILT_2 MISFIRE REPORT are not attached to report at all. In this instance I would only want to attach TILT_2 MISFIRE REPORT. I hope I am explaining correctly.
Here is the book of a script. Thanks for your help.
DECLARE
#Now DATETIME ,
#Monday DATETIME ,
#Friday DATETIME ,
#StartTime VARCHAR(16) ,
#EndTime VARCHAR(16) ,
#Message VARCHAR (50),
#FileName VARCHAR (50),
#Final VARCHAR (50)
SET #StartTime = '12:01:00AM'
SET #EndTime = '11:59:59PM'
SET #Now = GETDATE()
SET #Monday = DATEADD(dd, DATEDIFF(dd, 0, #Now), -0)
SET #Friday = DATEADD(dd, DATEDIFF(dd, 0, #Now), -0)
SET #Message = 'No results found for'
SET #FileName = CONVERT(varchar(30), GETDATE(), 107) + ' Sorter Stats 17P'
SET #Final = CAST(#message as varchar(70)) + ' ' + CAST(DATENAME (WEEKDAY, #Now)AS VARCHAR (30)) + ',' + ' ' + CONVERT(VARCHAR(30), #Now, 107)
-----------------------------------------------------------------
-----------------------------------------------------------------
IF EXISTS(
SELECT *
FROM [dbo].[StatData]
WHERE CreationTime BETWEEN #Monday + ' ' + #StartTime
AND #Friday + ' ' + #EndTime
AND SorterID IN ('TILT_1', 'TILT_2')
HAVING FLOOR(SUM(Throws)/2) = 0
)
BEGIN
EXEC msdb.dbo.sp_send_dbmail
#profile_name = 'My_profile',
#recipients = 'whatever#yep.com' ,
#subject = #FileName,
#importance = 'High',
#body = #Final,
#query_result_separator = ' ';
RETURN
END
-----------------------------------------------------------------
-----------------------------------------------------------------
ELSE
IF EXISTS (
SELECT 1
FROM [dbo].[MisfireLog]
WHERE RecordedPeriod BETWEEN #Monday + ' ' + #StartTime
AND #Friday + ' ' + #EndTime
AND WorkstationID IN ('T01', 'T02')
HAVING COUNT (MisfireOrder) = 0
)
BEGIN
--------------------START SORTER STATS.NO MISFIRE INFO-----------
-- Email Query--
DECLARE #Body varchar(max)
declare #TableHead varchar(max)
declare #TableTail varchar(max)
declare #mailitem_id as int
declare #statusMsg as varchar(max)
declare #Error as varchar(max)
declare #Note as varchar(max)
Set NoCount On;
set #mailitem_id = null
set #statusMsg = null
set #Error = null
set #Note = null
Set #TableTail = '</table></body></html>';
--HTML layout--
Set #TableHead =
'<html><head>' +
'<H1 style="color: #000000">Daily Sorter Stats</H1>' +
'<style>' +
'td {border: solid black 1px;padding-left:5px;padding-right:5px;padding-top:1px;padding-bottom:1px;font-size:9pt;color:Black;} ' +
'</style>' +
'</head>' +
'<body><table cellpadding=0 cellspacing=0 border=0>' +
'<tr bgcolor=#F6AC5D>'+
'<td align=center><b>Sorter</b></td>' +
'<td align=center><b>Items</b></td>' +
'<td align=center><b>Misfire</b></td></tr>';
--Select information for the Report--
Select #Body= (Select
[TD] = t1.Sorter,
[TD] = t1.Items,
[TD] = t2.Misfire
FROM
(
SELECT Items = floor(sum(Throws)/2)
,Sorter = 'TILT_1'
FROM [dbo].[StatData]
WHERE HourBlock BETWEEN #Monday + ' ' + #StartTime
AND #Friday + ' ' + #EndTime
AND SorterID = 'TILT_1'
)t1
CROSS JOIN
(
SELECT Misfire = isnull(FLOOR(sum(misfire)),0)
,'TILT_1' AS Sorter
FROM [dbo].[StatData]
WHERE HourBlock BETWEEN #Monday + ' ' + #StartTime
AND #Friday + ' ' + #EndTime
AND SorterID = 'TILT_1'
)t2
CROSS JOIN
(
SELECT DisabledTrays = isnull(COUNT(SorterID),0)
,'TILT_1' AS Sorter
FROM [dbo].[DisabledCarriers]
WHERE SorterID = 'TILT_1'
)t3
For XML raw('tr'), Elements)
-- Replace the entity codes and row numbers
Set #Body = Replace(#Body, '_x0020_', space(1))
Set #Body = Replace(#Body, '_x003D_', '=')
Set #Body = Replace(#Body, '<tr><TRRow>1</TRRow>', '<tr bgcolor=#C6CFFF>')
Set #Body = Replace(#Body, '<TRRow>0</TRRow>', '')
Set #Body = #TableHead + #Body + #TableTail
-- return output--
Select #Body
-----------------------------------------------------------------
-----------------------------------------------------------------
-- Email Query--
DECLARE #Body1 varchar(max)
declare #TableHead1 varchar(max)
declare #TableTail1 varchar(max)
declare #mailitem_id1 as int
declare #statusMsg1 as varchar(max)
declare #Error1 as varchar(max)
declare #Note1 as varchar(max)
Set NoCount On;
set #mailitem_id1 = null
set #statusMsg1 = null
set #Error1 = null
set #Note1 = null
Set #TableTail1 = '</table></body></html>';
--HTML layout--
Set #TableHead1 =
'<html><head>' +
'<style>' +
'td {border: solid black 1px;padding-left:5px;padding-right:5px;padding-top:1px;padding-bottom:1px;font-size:9pt;color:Black;} ' +
'</style>' +
'</head>' +
'<body><table cellpadding=0 cellspacing=0 border=0>' +
'<tr bgcolor=#F6AC5D>'+
'<td align=center><b>Sorter</b></td>' +
'<td align=center><b>Items</b></td>' +
'<td align=center><b>Misfire</b></td></tr>';
--Select information for the Report--
Select #Body1= (Select
[TD] = t1.Sorter,
[TD] = t1.Items,
[TD] = t2.Misfire
FROM
(
SELECT Items = isnull(floor(sum(Throws)/2),0)
,'TILT_2' AS Sorter
FROM [dbo].[StatData]
WHERE HourBlock BETWEEN #Monday + ' ' + #StartTime
AND #Friday + ' ' + #EndTime
AND SorterID = 'TILT_2'
)t1
CROSS JOIN
(
SELECT Misfire = isnull(FLOOR(sum(misfire)),0)
, 'TILT_2' AS Sorter
FROM [dbo].[StatData]
WHERE HourBlock BETWEEN #Monday + ' ' + #StartTime
AND #Friday + ' ' + #EndTime
AND SorterID = 'TILT_2'
)t2
For XML raw('tr'), Elements)
-- Replace the entity codes and row numbers
Set #Body1 = Replace(#Body1, '_x0020_', space(1))
Set #Body1 = Replace(#Body1, '_x003D_', '=')
Set #Body1 = Replace(#Body1, '<tr><TRRow>1</TRRow>', '<tr bgcolor=#C6CFFF>')
Set #Body1 = Replace(#Body1, '<TRRow>0</TRRow>', '')
Set #Body1 = #TableHead1 + #Body1 + #TableTail1
-- return output--
Select #Body1
-----------------------------------------------------------------
-----------------------------------------------------------------
--Email
DECLARE #BodyAll varchar(max)
SET #BodyAll = #Body + #Body1
EXEC msdb.dbo.sp_send_dbmail
#profile_name ='My_profile',
#recipients = 'whatever#yep.com',
#subject = #FileName,
#body = #BodyAll,
#body_format = 'HTML'
RETURN
END
ELSE
BEGIN
-----------------------------------------------------------------
-----------------------------------------------------------------
--------------------------------------ALL STATS.WITH MISFIRES----
-----------------------------------------------------------------
-----------------------------------------------------------------
-- Email Query--
DECLARE #Body2 varchar(max)
declare #TableHead2 varchar(max)
declare #TableTail2 varchar(max)
declare #mailitem_id2 as int
declare #statusMsg2 as varchar(max)
declare #Error2 as varchar(max)
declare #Note2 as varchar(max)
Set NoCount On;
set #mailitem_id2 = null
set #statusMsg2 = null
set #Error2 = null
set #Note2 = null
Set #TableTail2 = '</table></body></html>';
--HTML layout--
Set #TableHead2 =
'<html><head>' +
'<H1 style="color: #000000">Daily Sorter Stats</H1>' +
'<style>' +
'td {border: solid black 1px;padding-left:5px;padding-right:5px;padding-top:1px;padding-bottom:1px;font-size:9pt;color:Black;} ' +
'</style>' +
'</head>' +
'<body><table cellpadding=0 cellspacing=0 border=0>' +
'<tr bgcolor=#F6AC5D>'+
'<td align=center><b>Sorter</b></td>' +
'<td align=center><b>Items</b></td>' +
'<td align=center><b>Misfire</b></td></tr>';
--Select information for the Report--
Select #Body2= (Select
[TD] = t1.Sorter,
[TD] = t1.Items,
[TD] = t2.Misfire
FROM
(
SELECT Items = floor(sum(Throws)/2)
,Sorter = 'TILT_1'
FROM [dbo].[StatData]
WHERE HourBlock BETWEEN #Monday + ' ' + #StartTime
AND #Friday + ' ' + #EndTime
AND SorterID = 'TILT_1'
)t1
CROSS JOIN
(
SELECT Misfire = isnull(FLOOR(sum(misfire)),0)
,'TILT_1' AS Sorter
FROM [dbo].[StatData]
WHERE HourBlock BETWEEN #Monday + ' ' + #StartTime
AND #Friday + ' ' + #EndTime
AND SorterID = 'TILT_1'
)t2
For XML raw('tr'), Elements)
-- Replace the entity codes and row numbers
Set #Body2 = Replace(#Body2, '_x0020_', space(1))
Set #Body2 = Replace(#Body2, '_x003D_', '=')
Set #Body2 = Replace(#Body2, '<tr><TRRow>1</TRRow>', '<tr bgcolor=#C6CFFF>')
Set #Body2 = Replace(#Body2, '<TRRow>0</TRRow>', '')
Set #Body2 = #TableHead2 + #Body2 + #TableTail2
-- return output--
Select #Body2
-----------------------------------------------------------------
-----------------------------------------------------------------
-- Email Query--
DECLARE #Body3 varchar(max)
declare #TableHead3 varchar(max)
declare #TableTail3 varchar(max)
declare #mailitem_id3 as int
declare #statusMsg3 as varchar(max)
declare #Error3 as varchar(max)
declare #Note3 as varchar(max)
Set NoCount On;
set #mailitem_id3 = null
set #statusMsg3 = null
set #Error3= null
set #Note3 = null
Set #TableTail3 = '</table></body></html>';
--HTML layout--
Set #TableHead3 =
'<html><head>' +
'<style>' +
'td {border: solid black 1px;padding-left:5px;padding-right:5px;padding-top:1px;padding-bottom:1px;font-size:9pt;color:Black;} ' +
'</style>' +
'</head>' +
'<body><table cellpadding=0 cellspacing=0 border=0>' +
'<tr bgcolor=#F6AC5D>'+
'<td align=center><b>Sorter</b></td>' +
'<td align=center><b>Items</b></td>' +
'<td align=center><b>Misfire</b></td></tr>';
--Select information for the Report--
Select #Body3= (Select
[TD] = t1.Sorter,
[TD] = t1.Items,
[TD] = t2.Misfire
FROM
(
SELECT Items = isnull(floor(sum(Throws)/2),0)
,'TILT_2' AS Sorter
FROM [dbo].[StatData]
WHERE HourBlock BETWEEN #Monday + ' ' + #StartTime
AND #Friday + ' ' + #EndTime
AND SorterID = 'TILT_2'
)t1
CROSS JOIN
(
SELECT Misfire = isnull(FLOOR(sum(misfire)),0)
, 'TILT_2' AS Sorter
FROM [dbo].[StatData]
WHERE HourBlock BETWEEN #Monday + ' ' + #StartTime
AND #Friday + ' ' + #EndTime
AND SorterID = 'TILT_2'
)t2
For XML raw('tr'), Elements)
-- Replace the entity codes and row numbers
Set #Body3 = Replace(#Body3, '_x0020_', space(1))
Set #Body3 = Replace(#Body3, '_x003D_', '=')
Set #Body3 = Replace(#Body3, '<tr><TRRow>1</TRRow>', '<tr bgcolor=#C6CFFF>')
Set #Body3 = Replace(#Body3, '<TRRow>0</TRRow>', '')
Set #Body3 = #TableHead3 + #Body3 + #TableTail3
-- return output--
Select #Body3
-------------------------------------INSERT MISFIRE STATS HERE---
-- Email Query--
DECLARE #Body4 varchar(max)
declare #TableHead4 varchar(max)
declare #TableTail4 varchar(max)
declare #mailitem_id4 as int
declare #statusMsg4 as varchar(max)
declare #Error4 as varchar(max)
declare #Note4 as varchar(max)
Set NoCount On;
set #mailitem_id4 = null
set #statusMsg4 = null
set #Error4 = null
set #Note4 = null
Set #TableTail4 = '</table></body></html>';
--HTML layout--
Set #TableHead4 = '<html><head>' +
'<H1 style="color: #000000">Tilt 1 Misfire Report</H1>' +
'<style>' +
'td {border: solid black 1px;padding-left:5px;padding-right:5px;padding-top:1px;padding-bottom:1px;font-size:9pt;color:Black;} ' +
'</style>' +
'</head>' +
'<body><table cellpadding=0 cellspacing=0 border=0>' +
'<tr bgcolor=#F6AC5D>'+
'<td align=center><b>Misfire Count</b></td>' +
'<td align=center><b>Chute ID</b></td></tr>';
--Select information for the Report--
Select #Body4= (Select
[TD] = isnull(COUNT (MisfireOrder),0),
[TD] = ChuteID
from [dbo].[MisfireLog]
where RecordedPeriod BETWEEN #Monday + ' ' + #StartTime
AND #Friday + ' ' + #EndTime
AND WorkstationID = 'T01'
group by ChuteID
order by COUNT (MisfireOrder) desc
For XML raw('tr'), Elements)
-- Replace the entity codes and row numbers
Set #Body4 = Replace(#Body4, '_x0020_', space(1))
Set #Body4 = Replace(#Body4, '_x003D_', '=')
Set #Body4 = Replace(#Body4, '<tr><TRRow>1</TRRow>', '<tr bgcolor=#C6CFFF>')
Set #Body4 = Replace(#Body4, '<TRRow>0</TRRow>', '')
Set #Body4 = #TableHead4 + #Body4 + #TableTail4
-- return output--
Select #Body4
-----------------------------------------------------------------
-----------------------------------------------------------------
-- Email Query--
DECLARE #Body5 varchar(max)
declare #TableHead5 varchar(max)
declare #TableTail5 varchar(max)
declare #mailitem_id5 as int
declare #statusMsg5 as varchar(max)
declare #Error5 as varchar(max)
declare #Note5 as varchar(max)
Set NoCount On;
set #mailitem_id5 = null
set #statusMsg5 = null
set #Error5 = null
set #Note5 = null
Set #TableTail5 = '</table></body></html>';
--HTML layout--
Set #TableHead5 = '<html><head>' +
--'<H1 style="color: #000000">Tilt 2 Misfire Report</H1>' +
'<style>' +
'td {border: solid black 1px;padding-left:5px;padding-right:5px;padding-top:1px;padding-bottom:1px;font-size:9pt;color:Black;} ' +
'</style>' +
'</head>' +
'<body><table cellpadding=0 cellspacing=0 border=0>' +
'<tr bgcolor=#F6AC5D>'+
'<td align=center><b>Misfire Count</b></td>' +
'<td align=center><b>Carrier ID</b></td></tr>';
--Select information for the Report--
Select #Body5= (Select
[TD] = isnull(COUNT (MisfireOrder),0),
[TD] = CarrierID
from [dbo].[MisfireLog]
where RecordedPeriod BETWEEN #Monday + ' ' + #StartTime
AND #Friday + ' ' + #EndTime
AND WorkstationID = 'T01'
group by CarrierID
order by COUNT (MisfireOrder) desc
For XML raw('tr'), Elements)
-- Replace the entity codes and row numbers
Set #Body5 = Replace(#Body5, '_x0020_', space(1))
Set #Body5 = Replace(#Body5, '_x003D_', '=')
Set #Body5 = Replace(#Body5, '<tr><TRRow>1</TRRow>', '<tr bgcolor=#C6CFFF>')
Set #Body5 = Replace(#Body5, '<TRRow>0</TRRow>', '')
Set #Body5 = #TableHead5 + #Body5 + #TableTail5
-- return output--
Select #Body5
-----------------------------------------------------------------
-----------------------------------------------------------------
-- Email Query--
DECLARE #Body6 varchar(max)
declare #TableHead6 varchar(max)
declare #TableTail6 varchar(max)
declare #mailitem_id6 as int
declare #statusMsg6 as varchar(max)
declare #Error6 as varchar(max)
declare #Note6 as varchar(max)
Set NoCount On;
set #mailitem_id6 = null
set #statusMsg6 = null
set #Error6 = null
set #Note6 = null
Set #TableTail6 = '</table></body></html>';
--HTML layout--
Set #TableHead6= '<html><head>' +
'<H1 style="color: #000000">Tilt 2 Misfire Report</H1>' +
'<style>' +
'td {border: solid black 1px;padding-left:5px;padding-right:5px;padding-top:1px;padding-bottom:1px;font-size:9pt;color:Black;} ' +
'</style>' +
'</head>' +
'<body><table cellpadding=0 cellspacing=0 border=0>' +
'<tr bgcolor=#F6AC5D>'+
'<td align=center><b>Misfire Count</b></td>' +
'<td align=center><b>Chute ID</b></td></tr>';
--Select information for the Report--
Select #Body6= (Select
[TD] = isnull(COUNT (MisfireOrder),0),
[TD] = ChuteID
from [dbo].[MisfireLog]
where RecordedPeriod BETWEEN #Monday + ' ' + #StartTime
AND #Friday + ' ' + #EndTime
AND WorkstationID = 'T02'
group by ChuteID
order by COUNT (MisfireOrder) desc
For XML raw('tr'), Elements)
-- Replace the entity codes and row numbers
Set #Body6 = Replace(#Body6, '_x0020_', space(1))
Set #Body6 = Replace(#Body6, '_x003D_', '=')
Set #Body6 = Replace(#Body6, '<tr><TRRow>1</TRRow>', '<tr bgcolor=#C6CFFF>')
Set #Body6 = Replace(#Body6, '<TRRow>0</TRRow>', '')
Set #Body6 = #TableHead6 + #Body6 + #TableTail6
-- return output--
Select #Body6
-----------------------------------------------------------------
-----------------------------------------------------------------
-- Email Query--
DECLARE #Body7 varchar(max)
declare #TableHead7 varchar(max)
declare #TableTail7 varchar(max)
declare #mailitem_id7 as int
declare #statusMsg7 as varchar(max)
declare #Error7 as varchar(max)
declare #Note7 as varchar(max)
Set NoCount On;
set #mailitem_id7 = null
set #statusMsg7 = null
set #Error7 = null
set #Note7 = null
Set #TableTail7 = '</table></body></html>';
--HTML layout--
Set #TableHead7 = '<html><head>' +
--'<H1 style="color: #000000">Tilt 2 Misfire Report</H1>' +
'<style>' +
'td {border: solid black 1px;padding-left:5px;padding-right:5px;padding-top:1px;padding-bottom:1px;font-size:9pt;color:Black;} ' +
'</style>' +
'</head>' +
'<body><table cellpadding=0 cellspacing=0 border=0>' +
'<tr bgcolor=#F6AC5D>'+
'<td align=center><b>Misfire Count</b></td>' +
'<td align=center><b>Carrier ID</b></td></tr>';
--Select information for the Report--
Select #Body7= (Select
[TD] = isnull(COUNT (MisfireOrder),0),
[TD] = CarrierID
from [dbo].[MisfireLog]
where RecordedPeriod BETWEEN #Monday + ' ' + #StartTime
AND #Friday + ' ' + #EndTime
AND WorkstationID = 'T02'
group by CarrierID
order by COUNT (MisfireOrder) desc
For XML raw('tr'), Elements)
-- Replace the entity codes and row numbers
Set #Body7 = Replace(#Body7, '_x0020_', space(1))
Set #Body7 = Replace(#Body7, '_x003D_', '=')
Set #Body7 = Replace(#Body7, '<tr><TRRow>1</TRRow>', '<tr bgcolor=#C6CFFF>')
Set #Body7 = Replace(#Body7, '<TRRow>0</TRRow>', '')
Set #Body7 = #TableHead7 + #Body7 + #TableTail7
-- return output--
Select #Body7
-----------------------------------------------------------------
-----------------------------------------------------------------
--Email
DECLARE #BodyAll1 varchar(max)
SET #BodyAll1 = #Body2 + #Body3 + #Body4 + #Body5 + #Body6 + #Body7
EXEC msdb.dbo.sp_send_dbmail
#profile_name ='My_profile',
#recipients = 'whatever#yep.com',
#subject = #FileName,
#body = #BodyAll1,
#body_format = 'HTML'
END;

It looks like #Body4 + #Body5 are TILT1, and #Body6 + #Body7 are TILT2
You eventually combine these with:
DECLARE #BodyAll1 varchar(max)
SET #BodyAll1 = #Body2 + #Body3 + #Body4 + #Body5 + #Body6 + #Body7
It also looks like this is what gets the misfire count:
SELECT Misfire = isnull(FLOOR(sum(misfire)),0)
, 'TILT_1' AS Sorter --or `TILT_2`
FROM [PASTEUR].[WSS].[dbo].[StatData]
WHERE HourBlock BETWEEN #Monday + ' ' + #StartTime
AND #Friday + ' ' + #EndTime
AND SorterID = 'TILT_1' --or `TILT_2`
If that all is true, you should be able to simply wrap each TILT section in an IF() BEGIN.. END:
IF (SELECT ISNULL(FLOOR,SUM(MISFIRE)),0)
FROM [PASTEUR].[WSS].[dbo].[StatData]
WHERE HourBlock BETWEEN #Monday + ' ' + #StartTime
AND #Friday + ' ' + #EndTime
AND SorterID = 'TILT_1') > 0
BEGIN
--All of #Body4 and #Body5 code
END
Then remove your current IF EXISTS()
You could also handle this when you set #BodyAll1, but this way you don't run all of that extra code to create the TILT tables unless you plan to use those tables.

Related

Insert into a table where column values are passed as comma delimeted values

I have the following script where i want to insert into a table where column name can be passed as comma delimited values. Please suggest different approaches to achieve the following output.
Declare #col_by_source varchar(250) = 's1,s2,s3',
#column_by_target varchar(250) = 'c1,c2,c3',
#SQLString nvarchar(max)
Set #SQLString = 'INSERT INTO [dbo].[sourceTable] (
['+#col_by_source+'] )'
set #SQLString = #SQLString+' '+'SELECT '
Select #SQLString = #SQLString + QUOTENAME(split.a.value('.', 'VARCHAR(100)')) + ' AS '+#col_by_source+','
FROM (SELECT Cast ('<M>' + Replace(#column_by_target, ',', '</M><M>')+ '</M>' AS XML) AS Data) AS A
CROSS apply data.nodes ('/M') AS Split(a);
Set #SQLString = LEFT(#SQLString, LEN(#SQLString) - 1) + ')'
Set #SQLString = #SQLString + 'FROM tableA_source'
print #SQLString
OUTPUT:
INSERT INTO [dbo].[sourceTable] (
[s1,s2,s3] ) SELECT [c1] AS s1,s2,s3,[c2] AS s1,s2,s3,[c3] AS s1,s2,s3 FROM tableA_source
Expected Output:
INSERT INTO [dbo].[sourceTable] (
[s1,s2,s3] ) SELECT [c1] AS s1, [c2] AS s2,[c3] AS s3
FROM tableA_source
Make it as simple. You won't need an alias while doing insert....select.
try like this,
DECLARE #col_by_source VARCHAR(250) = 's1,s2,s3'
,#column_by_target VARCHAR(250) = 'c1,c2,c3'
,#SQLString NVARCHAR(max)
SET #SQLString = 'INSERT INTO [dbo].[sourceTable] (
' + #col_by_source + ' )'
SET #SQLString = #SQLString + ' ' + 'SELECT '
SELECT #SQLString = #SQLString + QUOTENAME(split.a.value('.', 'VARCHAR(100)')) + ' ,'
FROM (
SELECT Cast('<M>' + Replace(#column_by_target, ',', '</M><M>') + '</M>' AS XML) AS Data
) AS A
CROSS APPLY data.nodes('/M') AS Split(a);
SET #SQLString = LEFT(#SQLString, LEN(#SQLString) - 1) + ''
SET #SQLString = #SQLString + 'FROM tableA_source'
PRINT #SQLString

Sending an email in HTML format in SQL server not working properly

I want to send a query result as an HTML formatted email in SQL Server.
Here is my code,
DECLARE #Body varchar(max)
declare #TableHead varchar(max)
declare #TableTail varchar(max)
declare #mailitem_id as int
declare #statusMsg as varchar(max)
declare #Error as varchar(max)
declare #Note as varchar(max)
Set NoCount On;
set #mailitem_id = null
set #statusMsg = null
set #Error = null
set #Note = null
Set #TableTail = '</table></body></html>';
--HTML layout--
Set #TableHead = '<html><head>' +
'<H2 style="color: #000000">Rules changing in 15 Days</H2>' +
'<style>' +
'td {border: solid black 1px;padding-left:5px;padding-right:5px;padding- top:1px;padding-bottom:1px;font-size:9pt;color:Black;} ' +
'</style>' +
'</head>' +
'<body><table cellpadding=0 cellspacing=0 border=0>' +
'<tr bgcolor=#A6A6A6>'+
'<td align=center><b>ID</b></td>' +
'<td align=center><b>Name</b></td>' +
'<td align=center><b>From</b></td>' +
'<td align=center><b>To</b></td></tr>';
--Select information for the Report--
Select #Body= (Select
ID As [ID],
SUBSTRING(Name_List, 2, LEN(Name_List)-2) As [Name],
FromDate as [From],
[ToDate] as [To]
FROM tbl_ProductionDays dm(nolock)
where 1=1
and ToDate between GETDATE() and DATEADD(dd, 15, GETDATE())
For XML raw('tr'), Elements)
-- Replace the entity codes and row numbers
Set #Body = Replace(#Body, '_x0020_', space(1))
Set #Body = Replace(#Body, '_x003D_', '=')
Set #Body = Replace(#Body, '<tr><TRRow>1</TRRow>', '<tr bgcolor=#C6CFFF>')
Set #Body = Replace(#Body, '<TRRow>0</TRRow>', '')
Set #Body = #TableHead + #Body + #TableTail
-- return output--
--Email
EXEC msdb.dbo.sp_send_dbmail
#profile_name = 'SqlDBMAIL',
#recipients='abc#gmail.com',
#subject = 'notification email',
#body = #Body,
#body_format = 'HTML';
But this code does not send an email in a proper format. Every row is displayed in ID column only.
How to make it display in proper format?
You've got your column headers in table cells, but you need to do the same with your column data.
Changing your SELECT to something like this should do it:
Select #Body= (Select
'<td>'+ID+'</td>' As [ID],
'<td>'+SUBSTRING(Name_List, 2, LEN(Name_List)-2)+'</td>' As [Name],
'<td>'+FromDate+'</td>' as [From],
'<td>'+[ToDate]+'</td>' as [To]
FROM tbl_ProductionDays dm(nolock)
where 1=1
and ToDate between GETDATE() and DATEADD(dd, 15, GETDATE())
For XML raw('tr'), Elements)

BCP Double-quotes text qualifier output

I have a bcp command that is pushing the results of a query into a flat file that is comma delimited unicode. I need the fields to be encapsulated in double quotes with the text identifier being double quotes.
Here's an example of the csv output:
36029,2,Oct 11 2004 1:01AM,4,23537,0.10
Where it needs to be:
"36029","2","Oct 11 2004 1:01AM","4","23537","0.10"
I suspect it uses the -q flag but I'm not sure how to actually use the -q. The MS documentation is not doing much to help me out.
Sorry if this is a dupe, I looked hard I swear!
try this:
Exec Master..xp_Cmdshell 'bcp "SELECT '"' + col1 + '"', '"' + col2+ '"', '"' + col3+ '"'
FROM table1" queryout "C:\mcg1.csv" -c -t,"'
If you extract from within Eclipse it puts double quotes around text and dates. I do this from the view Data Source Explorer. Right click -> Data -> Extract...
You can also utilize SQL servers QuoteName function to specify the column that should have quotes. This also gives the ability to add any character in place of quotes
Exec Master..xp_Cmdshell 'bcp "SELECT QuoteName(col1,Char(34)),QuoteName(col2,Char(34)),... FROM table1" queryout "C:\test.csv" -c -t,"'
Take a look here to learn more
SQL Server BCP Utility Experts Guide
DECLARE #DBName VARCHAR(100) = 'dbname'
,#TableName VARCHAR(100) = 'example'
,#FileNamePath VARCHAR(100) = 'example.csv'
,#MaxRowsPerFile INT = 999999999
,#Resume BIT = 0
,#PrintVarValues BIT = 1
,#ConvertDates BIT = 1
,#QuotedStrings BIT = 0
,#delimitor VARCHAR(1) = ','
--Generate column names as a recordset
DECLARE #columns VARCHAR(8000)
,#columnsas VARCHAR(8000)
,#columnsformatted VARCHAR(8000)
,#sql VARCHAR(8000)
,#HeaderFile VARCHAR(100)
,#DataFile VARCHAR(100)
,#FileCount INT
,#TotalRows INT
,#RowCount INT
,#IntVariable INT
,#SQLString NVARCHAR(4000)
,#ParmDefinition NVARCHAR(512)
,#FileCountName VARCHAR(100)
,#PrimaryColumn NVARCHAR(128)
,#FileExtension VARCHAR(10)
,#Quote1 VARCHAR(10) = ''
,#Quote2 VARCHAR(10) = '';
IF (#QuotedStrings = 1)
BEGIN
SELECT #Quote1 = 'QUOTENAME('
,#Quote2 = ',CHAR(34))'
END
IF (
len(isnull(#DBName, '')) > 1
AND len(isnull(#TableName, '')) > 1
)
BEGIN
EXEC ('USE [' + #DBName + '];')
SELECT #FileCount = 1
,#RowCount = 1
IF (OBJECT_ID(N'dbo.#CreateExcel') IS NOT NULL)
BEGIN
IF (#Resume = 0)
BEGIN
DROP TABLE dbo.#CreateExcel
END
ELSE
BEGIN
SELECT #FileCount = FileCount
,#RowCount = [RowCount]
FROM dbo.#CreateExcel WITH (NOLOCK)
END
END
IF (OBJECT_ID(N'dbo.#CreateExcel') IS NULL)
BEGIN
CREATE TABLE dbo.#CreateExcel (
FileCount INT
,[RowCount] INT
)
INSERT INTO dbo.#CreateExcel (
FileCount
,[RowCount]
)
VALUES (
1
,1
)
END
SELECT #FileExtension = CASE
WHEN CHARINDEX('.', REVERSE(#FileNamePath)) > 1
THEN RIGHT(#FileNamePath, CHARINDEX('.', REVERSE(#FileNamePath)))
ELSE '.XLS'
END
SELECT #FileNamePath = CASE
WHEN CHARINDEX('.', REVERSE(#FileNamePath)) > 1
THEN LEFT(#FileNamePath, LEN(#FileNamePath) - CHARINDEX('.', REVERSE(#FileNamePath)))
ELSE #FileNamePath
END
SELECT #HeaderFile = substring(#FileNamePath, 1, len(#FileNamePath) - charindex('\', reverse(#FileNamePath))) + '\HeaderFile.xls'
SELECT #DataFile = substring(#FileNamePath, 1, len(#FileNamePath) - charindex('\', reverse(#FileNamePath))) + '\DataFile.xls'
SET #SQLString = N'SELECT #Primary_Column = bb.[name] FROM (' + N'SELECT TOP 1 co.[name] ' + N'FROM [' + #DBName + N'].[sys].[objects] ao with (nolock) ' + N' inner join [' + #DBName + N'].[sys].[columns] co with (nolock) ' + N' on ao.object_id = co.object_id ' + N'WHERE ao.[name] = ''' + #TableName + N'''' + N' AND ((co.is_identity=1) ' + N' or (co.column_id =1 and co.IS_NULLABLE=0) ' + N' or (co.system_type_id=36 /*uniqueidentifier*/) ' + N' or (co.system_type_id in (42,61,189) /*datetimes*/)) ' + N'ORDER BY co.is_identity desc, co.column_id asc, co.system_type_id asc) bb';
SET #ParmDefinition = N'#Primary_Column NVARCHAR(128) OUTPUT';
EXECUTE sp_executesql #SQLString
,#ParmDefinition
,#Primary_Column = #PrimaryColumn OUTPUT;
SET #SQLString = N'SELECT #cols=coalesce(#cols+'','','''')+''[''+co.[name]+'']'', ' + N'#colsas=coalesce(#colsas+'','','''')+''' + #Quote1 + '''''''+co.[name]+''''''' + #Quote2 + ''', ' + N'#colsformatted=coalesce(#colsformatted+'','','''')+CASE WHEN co.[system_type_id] in (98,167,175,231,239,241) THEN
''' + #Quote1 + 'REPLACE(REPLACE([''+co.[name]+''],CHAR(13),CHAR(32)),CHAR(10),CHAR(32))' + #Quote2 + '''
WHEN co.[system_type_id] in (35,99) THEN
''' + #Quote1 + 'REPLACE(REPLACE(CAST([''+co.[name]+''] AS VARCHAR(8000)),CHAR(13),CHAR(32)),CHAR(10),CHAR(32))' + #Quote2 + '''
WHEN ' + LTRIM(RTRIM(CAST(#ConvertDates AS INT))) + N'=1 AND co.[system_type_id] in (40,42,58,61) THEN
''' + #Quote1 + 'CONVERT(varchar(10),[''+co.[name]+''],101)+'''''''' ''''''''+LEFT(RIGHT(CONVERT(varchar(24),[''+co.[name]+''],109),12),8)+'''''''' ''''''''+RIGHT(LTRIM(RTRIM(CONVERT(varchar(24),[''+co.[name]+''],100))),2)' + #Quote2 + '''
ELSE ''[''+co.[name]+'']''
END ' + N'FROM [' + #DBName +
N'].[sys].[objects] ao with (nolock) ' + N' inner join [' + #DBName + N'].[sys].[columns] co with (nolock) ' + N' on ao.object_id = co.object_id ' + N'WHERE ao.[name] = ''' + #TableName + N'''';
SET #ParmDefinition = N'#cols VARCHAR(8000) OUTPUT, #colsas VARCHAR(8000) OUTPUT, #colsformatted VARCHAR(8000) OUTPUT';
EXECUTE sp_executesql #SQLString
,#ParmDefinition
,#cols = #columns OUTPUT
,#colsas = #columnsas OUTPUT
,#colsformatted = #columnsformatted OUTPUT;
--Create HeaderFile.XLS
SET #sql = 'exec master..xp_cmdshell ''bcp "SELECT ' + REPLACE(REPLACE(#columnsas, CHAR(34), CHAR(34) + CHAR(34)), CHAR(39), CHAR(39) + CHAR(39)) + '" queryout "' + #HeaderFile + '" -c -t ' + CASE
WHEN #delimitor IS NULL
THEN ''
ELSE #delimitor
END + ' -T'''
IF (#PrintVarValues = 1)
BEGIN
PRINT #sql
END
EXEC (#sql)
SET #SQLString = N'SELECT #Total_Rows = count(1) from [' + #DBName + N']..[' + #TableName + N'] with (nolock)';
SET #ParmDefinition = N'#Total_Rows INT OUTPUT';
EXECUTE sp_executesql #SQLString
,#ParmDefinition
,#Total_Rows = #TotalRows OUTPUT;
WHILE (#RowCount <= #TotalRows)
BEGIN
--Create incremental filename for each chuck of rows from table in database
IF (#PrintVarValues = 1)
BEGIN
PRINT 'Percent Complete: ' + ltrim(rtrim(cast(cast((#RowCount * 100) / #TotalRows AS INT) AS VARCHAR(10)))) + '%'
END
SET #FileCountName = #FileNamePath + Right(REPLICATE('0', 3) + ltrim(rtrim(CAST(#FileCount AS VARCHAR(4)))), 4) + #FileExtension
--populate data into incremental filename
SET #sql = 'exec master..xp_cmdshell ''bcp "SELECT ' + #columnsformatted + ' FROM ( SELECT ROW_NUMBER() OVER (ORDER BY [' + #PrimaryColumn + '] ASC) AS [ROW_NUMBER], ' + #columns + ' FROM [' + #DBName + ']..[' + #TableName + '] ) foo WHERE [ROW_NUMBER] BETWEEN ' + LTRIM(RTRIM(CAST(#RowCount AS NVARCHAR(10)))) + ' AND ' + LTRIM(RTRIM(CAST(#RowCount - 1 + #MaxRowsPerFile AS NVARCHAR(10)))) + '" queryout "' + #DataFile + '" -c -t ' + CASE
WHEN #delimitor IS NULL
THEN ''
ELSE #delimitor
END + ' -T'''
IF (#PrintVarValues = 1)
BEGIN
PRINT #sql
END
EXEC (#sql)
--Merge headerfile.xls with incremental filename
SET #sql = 'exec master..xp_cmdshell ''copy /b ' + #HeaderFile + '+' + #DataFile + ' ' + #FileCountName + ''''
IF (#PrintVarValues = 1)
BEGIN
PRINT #sql
END
EXEC (#sql)
--update TempCreateExcel table with running values in case needing to abort and restart from checkpoint reached.
SELECT #FileCount = #FileCount + 1
,#RowCount = #RowCount + #MaxRowsPerFile
UPDATE dbo.#CreateExcel
SET FileCount = #FileCount
,[RowCount] = #RowCount
END
IF (#PrintVarValues = 1)
BEGIN
PRINT 'Percent Complete: 100%'
END
DROP TABLE [dbo].#CreateExcel
END
use:
select col1, col2, quotename(col3, '\"') from table1 -- backslash before double quote to escape the "

T-SQL append number to variable

I couldn't find an answer to this....
I have three variables and need to switch between them in While Loop
Example:
DECLARE
#tableHTML NVARCHAR(MAX),
#email nvarchar(100),
#text1 nvarchar(100),
#text2 nvarchar(100),
#text3 nvarchar(100),
#number_suffix nvarchar(1)
SET #text1 = 'State of orders for Morfeus'
SET #text2 = 'State of orders for Fenix'
SET #text3 = 'State of orders for Perseus'
SET #number_suffix = 1
WHILE (#number_suffix < 4)
BEGIN
print #text(#number_suffix) /*and here is the problem */
SET #number_suffix = (#number_suffix + 1)
END
How do I append the number to variable #text please?
I am using MS SQL 2008
Do you want to append number to variable name? This is not possible. Why you need that, perhaps solution is more straightforward....
Try out following, perhaps id does what are you looking for:
DECLARE #cities TABLE(id int IDENTITY(1,1), cityName varchar(100))
INSERT INTO #cities(cityName) VALUES ('Morfeus'), ('Fenix'), ('Morfeus')
SELECT 'State of orders for ' + cityName
FROM #cities
Output:
State of orders for Morfeus
State of orders for Fenix
State of orders for Morfeus
To print number as well:
SELECT '#' + CAST(id AS varchar(2)) + ' State of orders for ' + cityName
FROM #cities
Output:
1 State of orders for Morfeus
2 State of orders for Fenix
3 State of orders for Morfeus
The question is not quite clear what your end game is but if I understand you correctly then something like this should work (note, you need to create the parse function first):
CREATE FUNCTION [dbo].[fnParseString]
(
#Section SMALLINT,
#Delimiter CHAR,
#Text VARCHAR(MAX)
)
RETURNS VARCHAR(8000)
AS
BEGIN
DECLARE #startindex NUMERIC(18,0),
#length NUMERIC(18,0),
#FieldPosition INT
SET #FieldPosition = ABS(#Section) - 1
SET #startindex = 0
WHILE #FieldPosition != 0
BEGIN
SET #FieldPosition = #FieldPosition - 1
SET #startindex = CHARINDEX(#Delimiter, #Text, #startindex + 1)
END
SET #Text = SUBSTRING(#Text, #startindex + 1, LEN(#Text) - #startindex)
SET #Text = SUBSTRING(#Text, 0, CHARINDEX(#Delimiter, #Text))
RETURN #Text
END
GO
DECLARE
#tableHTML NVARCHAR(MAX),
#email nvarchar(100),
#text nvarchar(100),
#number_suffix nvarchar(1)
SET #text = 'State of orders for Morfeus|State of orders for Fenix|State of orders for Perseus|'
SET #number_suffix = 1
WHILE (#number_suffix < 4)
BEGIN
PRINT dbo.fnParseString(#number_suffix, '|', #text)
SET #number_suffix = (#number_suffix + 1)
END
You can do it with Dynamic SQL but you'd need to reinitialize all you variables. The following will do it, but its a colossally bad idea, and you should use sll's answer instead
DECLARE
#tableHTML NVARCHAR(MAX),
#email nvarchar(100),
#number_suffix nvarchar(1),
#SQL nvarchar(max)
SET #number_suffix = 1
WHILE (#number_suffix < 4)
BEGIN
SET #SQL = N'
DECLARE #text1 nvarchar(100),
#text2 nvarchar(100),
#text3 nvarchar(100)
SET #text1 = ' + '''' + 'State of orders for Morfeus' + '''' +
'SET #text2 = ' + '''' + 'State of orders for Fenix' + '''' +
'SET #text3 = ' + '''' + 'State of orders for Perseus' + ''''
+
'PRINT #text' + #number_suffix
EXEC sp_executeSQL #SQL
SET #number_suffix = (#number_suffix + 1)
END

Convert a SQL query result table to an HTML table for email

I am running a SQL query that returns a table of results. I want to send the table in an email using dbo.sp_send_dbMail.
Is there a straightforward way within SQL to turn a table into an HTML table? Currently, I'm manually constructing it using COALESCE and putting the results into a varchar that I use as the emailBody.
Is there a better way to do this?
I made a dynamic proc which turns any random query into an HTML table, so you don't have to hardcode columns like in the other responses.
-- Description: Turns a query into a formatted HTML table. Useful for emails.
-- Any ORDER BY clause needs to be passed in the separate ORDER BY parameter.
-- =============================================
CREATE PROC [dbo].[spQueryToHtmlTable]
(
#query nvarchar(MAX), --A query to turn into HTML format. It should not include an ORDER BY clause.
#orderBy nvarchar(MAX) = NULL, --An optional ORDER BY clause. It should contain the words 'ORDER BY'.
#html nvarchar(MAX) = NULL OUTPUT --The HTML output of the procedure.
)
AS
BEGIN
SET NOCOUNT ON;
IF #orderBy IS NULL BEGIN
SET #orderBy = ''
END
SET #orderBy = REPLACE(#orderBy, '''', '''''');
DECLARE #realQuery nvarchar(MAX) = '
DECLARE #headerRow nvarchar(MAX);
DECLARE #cols nvarchar(MAX);
SELECT * INTO #dynSql FROM (' + #query + ') sub;
SELECT #cols = COALESCE(#cols + '', '''''''', '', '''') + ''['' + name + ''] AS ''''td''''''
FROM tempdb.sys.columns
WHERE object_id = object_id(''tempdb..#dynSql'')
ORDER BY column_id;
SET #cols = ''SET #html = CAST(( SELECT '' + #cols + '' FROM #dynSql ' + #orderBy + ' FOR XML PATH(''''tr''''), ELEMENTS XSINIL) AS nvarchar(max))''
EXEC sys.sp_executesql #cols, N''#html nvarchar(MAX) OUTPUT'', #html=#html OUTPUT
SELECT #headerRow = COALESCE(#headerRow + '''', '''') + ''<th>'' + name + ''</th>''
FROM tempdb.sys.columns
WHERE object_id = object_id(''tempdb..#dynSql'')
ORDER BY column_id;
SET #headerRow = ''<tr>'' + #headerRow + ''</tr>'';
SET #html = ''<table border="1">'' + #headerRow + #html + ''</table>'';
';
EXEC sys.sp_executesql #realQuery, N'#html nvarchar(MAX) OUTPUT', #html=#html OUTPUT
END
GO
Usage:
DECLARE #html nvarchar(MAX);
EXEC spQueryToHtmlTable #html = #html OUTPUT, #query = N'SELECT * FROM dbo.People', #orderBy = N'ORDER BY FirstName';
EXEC msdb.dbo.sp_send_dbmail
#profile_name = 'Foo',
#recipients = 'bar#baz.com;',
#subject = 'HTML email',
#body = #html,
#body_format = 'HTML',
#query_no_truncate = 1,
#attach_query_result_as_file = 0;
Related: Here is similar code to turn any arbitrary query into a CSV string.
Here is one way to do it from an article titled "Format query output into an HTML table - the easy way [archive]". You would need to substitute the details of your own query for the ones in this example, which gets a list of tables and a row count.
declare #body varchar(max)
set #body = cast( (
select td = dbtable + '</td><td>' + cast( entities as varchar(30) ) + '</td><td>' + cast( rows as varchar(30) )
from (
select dbtable = object_name( object_id ),
entities = count( distinct name ),
rows = count( * )
from sys.columns
group by object_name( object_id )
) as d
for xml path( 'tr' ), type ) as varchar(max) )
set #body = '<table cellpadding="2" cellspacing="2" border="1">'
+ '<tr><th>Database Table</th><th>Entity Count</th><th>Total Rows</th></tr>'
+ replace( replace( #body, '<', '<' ), '>', '>' )
+ '</table>'
print #body
Once you have #body, you can then use whatever email mechanism you want.
This might give you some idea --
CREATE TABLE #Temp
(
[Rank] [int],
[Player Name] [varchar](128),
[Ranking Points] [int],
[Country] [varchar](128)
)
INSERT INTO #Temp
SELECT 1,'Rafael Nadal',12390,'Spain'
UNION ALL
SELECT 2,'Roger Federer',7965,'Switzerland'
UNION ALL
SELECT 3,'Novak Djokovic',7880,'Serbia'
DECLARE #xml NVARCHAR(MAX)
DECLARE #body NVARCHAR(MAX)
SET #xml = CAST(( SELECT [Rank] AS 'td','',[Player Name] AS 'td','',
[Ranking Points] AS 'td','', Country AS 'td'
FROM #Temp ORDER BY Rank
FOR XML PATH('tr'), ELEMENTS ) AS NVARCHAR(MAX))
SET #body ='<html><body><H3>Tennis Rankings Info</H3>
<table border = 1>
<tr>
<th> Rank </th> <th> Player Name </th> <th> Ranking Points </th> <th> Country </th></tr>'
SET #body = #body + #xml +'</table></body></html>'
EXEC msdb.dbo.sp_send_dbmail
#profile_name = 'SQL ALERTING', -- replace with your SQL Database Mail Profile
#body = #body,
#body_format ='HTML',
#recipients = 'bruhaspathy#hotmail.com', -- replace with your email address
#subject = 'E-mail in Tabular Format' ;
DROP TABLE #Temp
Here my common used script below. I use this for running scripts on two tables/views with SQL job and send results as two HTML tables via mail. Ofcourse you should create mail profile before run this.
DECLARE #mailfrom varchar(max)
DECLARE #subject varchar(100)
DECLARE #tableHTML NVARCHAR(MAX), #tableHTML1 NVARCHAR(MAX), #tableHTML2 NVARCHAR(MAX), #mailbody NVARCHAR(MAX)
DECLARE #Table1 NVARCHAR(MAX), #Table2 NVARCHAR(MAX)
DECLARE #jobName varchar(100)
SELECT #jobName = name from msdb..sysjobs where job_id = $(ESCAPE_NONE(JOBID))
-- If the result set is not empty then fill the Table1 HTML table
IF (SELECT COUNT(*) FROM [Database].[Schema].[Table1]) > 0
BEGIN
SET #Table1 = N''
SELECT #Table1 = #Table1 + '<tr style="font-size:13px;background-color:#FFFFFF">' +
'<td>' + ColumnText + '</td>' +
'<td>' + CAST(ColumnNumber as nvarchar(30)) + '</td>' + '</tr>'
FROM [Database].[Schema].[Table1]
ORDER BY ColumnText,ColumnNumber
SET #tableHTML1 =
N'<table border="1" align="Left" cellpadding="2" cellspacing="0" style="color:black;font-family:arial,helvetica,sans-serif;text-align:left;" >' +
N'<tr style ="font-size:13px;font-weight: normal;background: #FFFFFF">
<th align=left>ColumnTextHeader1</th>
<th align=left>ColumnNumberHeader2</th> </tr>' + #Table1 + '</table>'
END
ELSE
BEGIN
SET #tableHTML1 = N''
SET #Table1 = N''
END
-- If the result set is not empty then fill the Table2 HTML table
IF (SELECT COUNT(*) FROM [Database].[Schema].[Table2]) > 0
BEGIN
SET #Table2 = N''
SELECT #Table2 = #Table2 + '<tr style="font-size:13px;background-color:#FFFFFF">' +
'<td>' + ColumnText + '</td>' +
'<td>' + CAST(ColumnNumber as nvarchar(30)) + '</td>' + '</tr>'
FROM [Database].[Schema].[Table2]
ORDER BY ColumnText,ColumnNumber
SET #tableHTML2 =
N'<table border="1" align="Left" cellpadding="2" cellspacing="0" style="color:black;font-family:arial,helvetica,sans-serif;text-align:left;" >' +
N'<tr style ="font-size:13px;font-weight: normal;background: #FFFFFF">
<th align=left>ColumnTextHeader1</th>
<th align=left>ColumnNumberHeader2</th> </tr>' + #Table2 + '</table>'
END
ELSE
BEGIN
SET #tableHTML2 = N''
SET #Table2 = N''
END
SET #tableHTML = #tableHTML1 + #tableHTML2
-- If result sets from Table1 and Table2 are empty, then don't sent mail.
IF (SELECT #tableHTML) <> ''
BEGIN
SET #mailbody = N' Write mail text here<br><br>' + #tableHTML
SELECT #mailfrom = 'SQL Server <' + cast(SERVERPROPERTY('ComputerNamePhysicalNETBIOS') as varchar(50)) + '#domain.com>'
SELECT #subject = N'Mail Subject [Job: ' + #jobName + ']'
EXEC msdb.dbo.sp_send_dbmail
#profile_name= 'mailprofilename',
#recipients= '<mailaddress#domain.com>',
#from_address = #mailfrom,
#reply_to = '<mailaddress#domain.com>',
#subject = #subject,
#body = #mailbody,
#body_format = 'HTML'
-- ,#importance = 'HIGH'
END
JustinStolle's answer in a different way. A few notes:
The print statement may truncate the string to 4000 characters, but my test string for example was 9520 characters in length.
The [tr/th] indicates hierarchy, e.g., <tr><th>...</th></tr>.
The [#name] adds fields as XML attributes.
MS SQL XML concatenates fields of the same name, so null in between fields prevents that.
declare #body nvarchar(max)
select #body = cast((
select N'2' [#cellpadding], N'2' [#cellspacing], N'1' [#border],
N'Database Table' [tr/th], null [tr/td],
N'Entity Count' [tr/th], null [tr/td],
N'Total Rows' [tr/th], null,
(select object_name( object_id ) [td], null,
count( distinct name ) [td], null,
count( * ) [td], null
from sys.columns
group by object_name( object_id )
for xml path('tr'), type)
for xml path('table'), type
) as nvarchar(max))
print #body -- only shows up to 4000 characters depending
based on JustinStolle code (thank you), I wanted a solution that could be generic without having to specify the column names.
This sample is using the data of a temp table but of course it can be adjusted as required.
Here is what I got:
DECLARE #htmlTH VARCHAR(MAX) = '',
#htmlTD VARCHAR(MAX)
--get header, columns name
SELECT #htmlTH = #htmlTH + '<TH>' + name + '</TH>' FROM tempdb.sys.columns WHERE object_id = OBJECT_ID('tempdb.dbo.#results')
--convert table to XML PATH, ELEMENTS XSINIL is used to include NULL values
SET #htmlTD = (SELECT * FROM #results FOR XML PATH('TR'), ELEMENTS XSINIL)
--convert the way ELEMENTS XSINIL display NULL to display word NULL
SET #htmlTD = REPLACE(#htmlTD, ' xsi:nil="true"/>', '>NULL</TD>')
SET #htmlTD = REPLACE(#htmlTD, '<TR xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">', '<TR>')
--FOR XML PATH will set tags for each column name, <columnName1>abc</columnName1><columnName2>def</columnName2>
--this will replace all the column names with TD (html table data tag)
SELECT #htmlTD = REPLACE(REPLACE(#htmlTD, '<' + name + '>', '<TD>'), '</' + name + '>', '</TD>')
FROM tempdb.sys.columns WHERE object_id = OBJECT_ID('tempdb.dbo.#results')
SELECT '<TABLE cellpadding="2" cellspacing="2" border="1">'
+ '<TR>' + #htmlTH + '</TR>'
+ #htmlTD
+ '</TABLE>'
Suppose someone found his way here and does not understand the usage of the marked answer SQL, please read mine... it is edited and works. Table:staff, columns:staffname,staffphone and staffDOB
declare #body varchar(max)
-- Create the body
set #body = cast( (
select td = dbtable + '</td><td>' + cast( phone as varchar(30) ) + '</td><td>' + cast( age as varchar(30) )
from (
select dbtable = StaffName ,
phone = staffphone,
age = datepart(day,staffdob)
from staff
group by staffname,StaffPhone,StaffDOB
) as d
for xml path( 'tr' ), type ) as varchar(max) )
set #body = '<table cellpadding="2" cellspacing="2" border="1">'
+ '<tr><th>Database Table</th><th>Entity Count</th><th>Total Rows</th></tr>'
+ replace( replace( #body, '<', '<' ), '>', '>' )
+ '<table>'
print #body
I tried printing Multiple Tables using Mahesh Example above. Posting for convenience of others
USE MyDataBase
DECLARE #RECORDS_THAT_NEED_TO_SEND_EMAIL TABLE (ID INT IDENTITY(1,1),
POS_ID INT,
POS_NUM VARCHAR(100) NULL,
DEPARTMENT VARCHAR(100) NULL,
DISTRICT VARCHAR(50) NULL,
COST_LOC VARCHAR(100) NULL,
EMPLOYEE_NAME VARCHAR(200) NULL)
INSERT INTO #RECORDS_THAT_NEED_TO_SEND_EMAIL(POS_ID,POS_NUM,DISTRICT,COST_LOC,DEPARTMENT,EMPLOYEE_NAME)
SELECT uvwpos.POS_ID,uvwpos.POS_NUM,uvwpos.DISTRICT, uvwpos.COST_LOC,uvwpos.DEPARTMENT,uvemp.LAST_NAME + ' ' + uvemp.FIRST_NAME
FROM uvwPOSITIONS uvwpos LEFT JOIN uvwEMPLOYEES uvemp
on uvemp.POS_ID=uvwpos.POS_ID
WHERE uvwpos.ACTIVE=1 AND uvwpos.POS_NUM LIKE 'sde%'AND (
(RTRIM(LTRIM(LEFT(uvwpos.DEPARTMENT,LEN(uvwpos.DEPARTMENT)-1))) <> RTRIM(LTRIM(uvwpos.COST_LOC)))
OR (uvwpos.DISTRICT IS NULL)
OR (uvwpos.COST_LOC IS NULL) )
DECLARE #RESULT_DISTRICT_ISEMPTY varchar(4000)
DECLARE #RESULT_COST_LOC_ISEMPTY varchar(4000)
DECLARE #RESULT_COST_LOC__AND_DISTRICT_NOT_MATCHING varchar(4000)
DECLARE #BODY NVARCHAR(MAX)
DECLARE #HTMLHEADER VARCHAR(100)
DECLARE #HTMLFOOTER VARCHAR(100)
SET #HTMLHEADER='<html><body>'
SET #HTMLFOOTER ='</body></html>'
SET #RESULT_DISTRICT_ISEMPTY = '';
SET #BODY =#HTMLHEADER+ '<H3>PositionNumber where District is Empty.</H3>
<table border = 1>
<tr>
<th> POS_ID </th> <th> POS_NUM </th> <th> DEPARTMENT </th> <th> DISTRICT </th> <th> COST_LOC </th></tr>'
SET #RESULT_DISTRICT_ISEMPTY = CAST(( SELECT [POS_ID] AS 'td','',RTRIM([POS_NUM]) AS 'td','',
ISNULL(LEFT(DEPARTMENT,LEN(DEPARTMENT)-1),' ') AS 'td','', ISNULL([DISTRICT],' ') AS 'td','',ISNULL([COST_LOC],' ') AS 'td'
FROM #RECORDS_THAT_NEED_TO_SEND_EMAIL
WHERE DISTRICT IS NULL
FOR XML PATH('tr'), ELEMENTS ) AS VARCHAR(MAX))
SET #BODY = #BODY + #RESULT_DISTRICT_ISEMPTY +'</table>'
DECLARE #RESULT_COST_LOC_ISEMPTY_HEADER VARCHAR(400)
SET #RESULT_COST_LOC_ISEMPTY_HEADER ='<H3>PositionNumber where COST_LOC is Empty.</H3>
<table border = 1>
<tr>
<th> POS_ID </th> <th> POS_NUM </th> <th> DEPARTMENT </th> <th> DISTRICT </th> <th> COST_LOC </th></tr>'
SET #RESULT_COST_LOC_ISEMPTY = CAST(( SELECT [POS_ID] AS 'td','',RTRIM([POS_NUM]) AS 'td','',
ISNULL(LEFT(DEPARTMENT,LEN(DEPARTMENT)-1),' ') AS 'td','', ISNULL([DISTRICT],' ') AS 'td','',ISNULL([COST_LOC],' ') AS 'td'
FROM #RECORDS_THAT_NEED_TO_SEND_EMAIL
WHERE COST_LOC IS NULL
FOR XML PATH('tr'), ELEMENTS ) AS VARCHAR(MAX))
SET #BODY = #BODY + #RESULT_COST_LOC_ISEMPTY_HEADER+ #RESULT_COST_LOC_ISEMPTY +'</table>'
DECLARE #RESULT_COST_LOC__AND_DISTRICT_NOT_MATCHING_HEADER VARCHAR(400)
SET #RESULT_COST_LOC__AND_DISTRICT_NOT_MATCHING_HEADER='<H3>PositionNumber where Department and Cost Center are Not Macthing.</H3>
<table border = 1>
<tr>
<th> POS_ID </th> <th> POS_NUM </th> <th> DEPARTMENT </th> <th> DISTRICT </th> <th> COST_LOC </th></tr>'
SET #RESULT_COST_LOC__AND_DISTRICT_NOT_MATCHING = CAST(( SELECT [POS_ID] AS 'td','',RTRIM([POS_NUM]) AS 'td','',
ISNULL(LEFT(DEPARTMENT,LEN(DEPARTMENT)-1),' ') AS 'td','', ISNULL([DISTRICT],' ') AS 'td','',ISNULL([COST_LOC],' ') AS 'td'
FROM #RECORDS_THAT_NEED_TO_SEND_EMAIL
WHERE
(RTRIM(LTRIM(LEFT(DEPARTMENT,LEN(DEPARTMENT)-1))) <> RTRIM(LTRIM(COST_LOC)))
FOR XML PATH('tr'), ELEMENTS ) AS VARCHAR(MAX))
SET #BODY = #BODY + #RESULT_COST_LOC__AND_DISTRICT_NOT_MATCHING_HEADER+ #RESULT_COST_LOC__AND_DISTRICT_NOT_MATCHING +'</table>'
SET #BODY = #BODY + #HTMLFOOTER
USE DDDADMINISTRATION_DB
--SEND EMAIL
exec DDDADMINISTRATION_DB.dbo.uspSMTP_NOTIFY_HTML
#EmailSubject = 'District,Department & CostCenter Discrepancies',
#EmailMessage = #BODY,
#ToEmailAddress = 'Slohani#azdes.gov',
#FromEmailAddress = 'Slohani#azdes.gov'
EXEC msdb.dbo.sp_send_dbmail
#profile_name = 'MY POROFILE', -- replace with your SQL Database Mail Profile
#body = #BODY,
#body_format ='HTML',
#recipients = 'Recepients#internalmail.com', -- replace with your email address
#subject = 'District,Department & CostCenter Discrepancies' ;
All the other answers use variables and SET operations. Here's a way to do it within a select statement. Just drop this in as a column in your existing select.
(SELECT
'<table style=''font-family:"Verdana"; font-size: 10pt''>'
+ '<tr bgcolor="#9DBED4"><th>col1</th><th>col2</th><th>col3</th><th>col4</th><th>col5</th></tr>'
+ replace( replace( body, '<', '<' ), '>', '>' )
+ '</table>'
FROM
(
select cast( (
select td = cast(col1 as varchar(5)) + '</td><td align="right">' + col2 + '</td><td>' + col3 + '</td><td align="right">' + cast(col4 as varchar(5)) + '</td><td align="right">' + cast(col5 as varchar(5)) + '</td>'
from (
select col1 = col1,
col2 = col2,
col3 = col3,
col4 = col4,
col5 = col5
from m_LineLevel as onml
where onml.pkey = oni.pkey
) as d
for xml path( 'tr' ), type ) as varchar(max) ) as body
) as bodycte) as LineTable
Following piece of code, I have prepared for generating the HTML file for documentation which includes Table Name and Purpose in each table and Table Metadata information. It might be helpful!
use Your_Database_Name;
print '<!DOCTYPE html>'
PRINT '<html><body>'
SET NOCOUNT ON
DECLARE #tableName VARCHAR(30)
DECLARE tableCursor CURSOR LOCAL FAST_FORWARD FOR
SELECT T.name AS TableName
FROM sys.objects AS T
WHERE T.type_desc = 'USER_TABLE'
ORDER BY T.name
OPEN tableCursor
FETCH NEXT FROM tableCursor INTO #tableName
WHILE ##FETCH_STATUS = 0 BEGIN
print '<table>'
print '<tr><td><b>Table Name: <b></td><td>'+#tableName+'</td></tr>'
print '<tr><td><b>Prupose: <b></td><td>????YOu can Fill later????</td></tr>'
print '</table>'
print '<table>'
print '<tr><th>ColumnName</th><th>DataType</th><th>Size</th><th>PrecScale</th><th>Nullable</th><th>Default</th><th>Identity</th><th>Remarks</th></tr>'
SELECT concat('<tr><td>',
LEFT(C.name, 30) /*AS ColumnName*/,'</td><td>',
LEFT(ISC.DATA_TYPE, 10) /*AS DataType*/,'</td><td>',
C.max_length /*AS Size*/,'</td><td>',
CAST(P.precision AS VARCHAR(4)) + '/' + CAST(P.scale AS VARCHAR(4)) /*AS PrecScale*/,'</td><td>',
CASE WHEN C.is_nullable = 1 THEN 'Null' ELSE 'No Null' END /*AS [Nullable]*/,'</td><td>',
LEFT(ISNULL(ISC.COLUMN_DEFAULT, ' '), 5) /*AS [Default]*/,'</td><td>',
CASE WHEN C.is_identity = 1 THEN 'Identity' ELSE '' END /*AS [Identity]*/,'</td><td></td></tr>')
FROM sys.objects AS T
JOIN sys.columns AS C ON T.object_id = C.object_id
JOIN sys.types AS P ON C.system_type_id = P.system_type_id and c.user_type_id = p.user_type_id
JOIN INFORMATION_SCHEMA.COLUMNS AS ISC ON T.name = ISC.TABLE_NAME AND C.name = ISC.COLUMN_NAME
WHERE T.type_desc = 'USER_TABLE'
AND T.name = #tableName
ORDER BY T.name, ISC.ORDINAL_POSITION
print '</table>'
print '</br>'
FETCH NEXT FROM tableCursor INTO #tableName
END
CLOSE tableCursor
DEALLOCATE tableCursor
SET NOCOUNT OFF
PRINT '</body></html>'
Here is my implementation: any query result to html table.
I'm creating some helper procedures to achieve this. These helper procedures are flexible, and may be reused in various contexts.
fnValidateDynamicSql - to validate passed dynamic statement
spAlterTblByRs - to save any SQL statement result to #table. Allows to completely remove dynamic SQL from the code
spQueryResultAsHtmlTable - creates html table from any passed SQL statement
Enjoy :)
CREATE FUNCTION [dbo].[fnValidateDynamicSql]
(#Sql NVARCHAR(MAX), /* dynamic sql statement */
#Params NVARCHAR(MAX) /* parameters, if dynamic SQL is parametrized. Pass NULL if there are no params */
)
RETURNS NVARCHAR(MAX)
AS
/* Check or #Sql statement is valid
* Returns NULL if valid, exception message otherwise
*/
BEGIN
DECLARE #Result VARCHAR(1000);
IF EXISTS (SELECT NULL
FROM [sys].[dm_exec_describe_first_result_set](#Sql, #Params, 0)
WHERE [error_message] IS NOT NULL
AND [error_number] IS NOT NULL
AND [error_severity] IS NOT NULL
AND [error_state] IS NOT NULL
AND [error_type] IS NOT NULL
AND [error_type_desc] IS NOT NULL)
BEGIN
SELECT #Result = [error_message]
FROM [sys].[dm_exec_describe_first_result_set](#Sql, #Params, 0)
WHERE [column_ordinal] = 0;
END;
IF NULLIF(LTRIM(RTRIM(#Sql)), '') IS NULL
SET #Result = '#Sql is NULL';
RETURN #Result;
END;
GO
CREATE PROCEDURE [dbo].[spAlterTblByRs]
#ErrCode INT OUT,
#ErrMsg VARCHAR(4000) OUT,
#Sql NVARCHAR(MAX), /* Query stmt */
#Params NVARCHAR(MAX) = NULL, /* Query parameters (like in sp_executesql) */
#Tbl NVARCHAR(256), /* Table name */
#DummyCol NVARCHAR(256), /* Dummy column name (will be removed) */
#PopulateTable BIT = NULL /* If 1, then populate altered table by #Sql query data */
AS
/* Alters table by recordset to be used. Populates data, if required. */
BEGIN
SET NOCOUNT ON;
SET ARITHABORT ON;
BEGIN TRY
DECLARE #ERR_CODE_OK INT = 0
, #ERR_CODE_FAILURE INT = 50000;
SET #ErrCode = #ERR_CODE_OK;
IF NULLIF(LTRIM(RTRIM(#Tbl)), '') IS NULL THROW #ERR_CODE_FAILURE, '#Tbl is empty', 1;
IF NULLIF(LTRIM(RTRIM(#DummyCol)), '') IS NULL THROW #ERR_CODE_FAILURE, '#DummyCol is empty', 1;
IF [dbo].[fnValidateDynamicSql](#Sql, #Params) IS NOT NULL
BEGIN
SET #ErrMsg = 'Invalid #Sql received: ' + [dbo].[fnValidateDynamicSql](#Sql, #Params);
;THROW #ERR_CODE_FAILURE, #ErrMsg, 1;
END;
DECLARE #AlterStmt NVARCHAR(MAX) = SPACE(0);
DECLARE #RemColStmt NVARCHAR(MAX) = SPACE(0);
-- prepare existing table alter Stmt by previuos rs structure
SET #AlterStmt = 'ALTER TABLE ' + #tbl + ' ADD ' + CHAR(13);
;WITH [rsStructure] AS (
SELECT
[name]
, [system_type_name]
, [is_nullable]
FROM [sys].[dm_exec_describe_first_result_set](
#Sql
, #Params
, 0
)
)
SELECT
#AlterStmt += QUOTENAME([name]) + SPACE(1) + [system_type_name] + IIF([is_nullable] = 0, ' NOT NULL' , SPACE(0)) + ',' + CHAR(13)
FROM [rsStructure];
SET #AlterStmt = LEFT(#AlterStmt, LEN(#AlterStmt) - 2);
-- finally update table structure
EXEC [sys].[sp_executesql] #AlterStmt;
-- remove dummy column
SET #RemColStmt = 'ALTER TABLE ' + #tbl + ' DROP COLUMN ' + #DummyCol;
EXEC [sys].[sp_executesql] #RemColStmt;
-- populate table with #Sql statement data
IF #PopulateTable = 1
BEGIN
EXEC('INSERT INTO ' + #tbl + ' ' + #sql);
END;
END TRY
BEGIN CATCH
/* Use some error formatting sp instead */
SELECT #ErrCode = ERROR_NUMBER()
, #ErrMsg = ERROR_MESSAGE();
END CATCH
RETURN #ErrCode;
END
GO
GO
CREATE PROCEDURE [dbo].[spQueryResultAsHtmlTable]
#ErrCode INT OUT
, #ErrMsg NVARCHAR(4000) OUT
, #Sql NVARCHAR(MAX)
, #Params NVARCHAR(MAX)
, #HtmlTable NVARCHAR(MAX) OUT
AS
/* Makes Html table by result, returned by provided #Query
*/
BEGIN
SET NOCOUNT ON;
SET ARITHABORT ON;
BEGIN TRY
DECLARE #ERR_CODE_OK INT = 0
, #ERR_CODE_FAILED INT = 50000;
SET #ErrCode = #ERR_CODE_OK;
DECLARE #HtmlAsHml XML
, #ColumnList NVARCHAR(MAX) = SPACE(0);
IF NULLIF(LTRIM(RTRIM(#Sql)), SPACE(0)) IS NULL THROW #ERR_CODE_FAILED, 'Empty #Query received', 1;
IF OBJECT_ID('tempdb..#QueryResult') IS NOT NULL DROP TABLE [#QueryResult];
CREATE TABLE [#QueryResult] ([dummy_col] BIT);
EXEC [dbo].[spAlterTblByRs]
#ErrCode = #ErrCode OUT
, #ErrMsg = #ErrMsg OUT
, #Sql = #Sql
, #Params = #Params
, #Tbl = '#QueryResult'
, #DummyCol = 'dummy_col'
, #PopulateTable = 1;
IF #ErrCode <> 0 THROW #ErrCode, #ErrMsg, 1;
SELECT #ColumnList += IIF([column_ordinal] = 1, SPACE(0), ',') + '[td] = [' + [name] + ']'
FROM [sys].[dm_exec_describe_first_result_set](
#Sql /* #tsql */
, #Params /* #params */
, 0 /* #browse_information_mode */
)
ORDER BY [column_ordinal] ASC;
DECLARE #h XML
, #d XML;
/* Prepare headers */
;WITH [headers] AS (
SELECT [h] = CONVERT(XML, (SELECT
[th] = [name]
FROM [sys].[dm_exec_describe_first_result_set](
#Sql /* #tsql */
, #Params /* #params */
, 0 /* #browse_information_mode */
)
ORDER BY [column_ordinal] ASC
FOR XML PATH(''), ROOT('tr')))
)
SELECT #h = [h] FROM [headers];
/* Prepare rows */
SET #sql = N'
;WITH [data] AS (
SELECT [d] = (SELECT
' + #ColumnList + '
FROM [#QueryResult]
FOR XML RAW (''tr''), ELEMENTS XSINIL, TYPE)
)
SELECT #d = [d] FROM [data]';
SET #params = N'#d xml output';
EXECUTE [sp_executesql]
#stmt = #sql
, #params = #params
, #d = #d OUTPUT;
/* Make table html */
SET #HtmlAsHml = CONVERT(XML, (SELECT [*] = #h, [*] = #d FOR XML PATH('table')));
SET #HtmlAsHml.modify('insert attribute cellpadding {"2"} into (table)[1]')
SET #HtmlAsHml.modify('insert attribute cellspacing {"2"} into (table)[1]')
SET #HtmlAsHml.modify('insert attribute border {"1"} into (table)[1]')
/* Prepare value to be returned */
SET #HtmlTable = CONVERT(NVARCHAR(MAX), #HtmlAsHml);
END TRY
BEGIN CATCH
/* Use some error formatting sp instead */
SELECT #ErrCode = ERROR_NUMBER()
, #ErrMsg = ERROR_MESSAGE();
END CATCH;
RETURN #ErrCode;
END;
GO
/* Usage */
DECLARE
#ErrCode INT
, #ErrMsg NVARCHAR(4000)
, #Sql NVARCHAR(MAX) = 'select top (10) * from sys.tables'
, #HtmlTable NVARCHAR(MAX);
EXEC [dbo].[spQueryResultAsHtmlTable]
#ErrCode = #ErrCode OUT
, #ErrMsg = #ErrMsg OUT
, #Sql = #Sql
, #Params = NULL
, #HtmlTable = #HtmlTable OUT; /* YOur desired html table here */
IF #ErrCode <> 0 THROW #ErrCode, #ErrMsg, 1;