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;