How can I add ##rowcount to this SQL query - html

SET #tableHTML =
N'<H1>Report Heading</H1>' +
N'<table border="1">' +
N'<th>Check Number</th>' +
N'<th>Last Operator Date</th>' +
N'<th>Last Timestamp</th>' +
N'<th>Run Date</th>' +
N'<th>Issued Check Number</th>' +
N'<th>Error Description</th>' +
'<tr>' +
CAST ( ( SELECT td = S.CHK_NUM, '',
td = S.LAST_OPER_ID, '',
td = S.LAST_TIMESTMP, '',
td = S.RUN_DT, '',
td = ISNULL(S.RE_ISSUE_CHK_NUM,-1), '',
td = ISNULL(S.ERR_DESC,'<null>'), ''
FROM STAGNG_CDDP_ERR_RCD S
FOR XML PATH('tr'), TYPE
) AS NVARCHAR(MAX) ) +
N'</table>' ;
PRINT #tableHTML
I want to count the resulting rows and assign it to a variable. How can that be achieved?

Just add a count query:
DECLARE #tableHTML NVARCHAR(MAX), #Count int;
SELECT #tableHTML =
N'<H1>Report Heading</H1>' +
N'<table border="1">' +
N'<th>Check Number</th>' +
N'<th>Last Operator Date</th>' +
N'<th>Last Timestamp</th>' +
N'<th>Run Date</th>' +
N'<th>Issued Check Number</th>' +
N'<th>Error Description</th>' +
'<tr>' +
CAST ( ( SELECT td = S.CHK_NUM, '',
td = S.LAST_OPER_ID, '',
td = S.LAST_TIMESTMP, '',
td = S.RUN_DT, '',
td = ISNULL(S.RE_ISSUE_CHK_NUM,-1), '',
td = ISNULL(S.ERR_DESC,'<null>'), ''
FROM STAGNG_CDDP_ERR_RCD S
FOR XML PATH('tr'), TYPE
) AS NVARCHAR(MAX) ) +
N'</table>'
, #Count = (SELECT COUNT(*) FROM STAGNG_CDDP_ERR_RCD);
PRINT #Count;
PRINT #tableHTML;

Related

Change the Colour of a value in a SQL Server DB Mail

I have created a DB Mail alert that sends out a HTML formatted table showing the pass or fail status of my SQL agents.
The alert works well, but the user has request an additional change where they want conditional formating on Pass/Fail status of the data, where failed status is to be highlighted RED and pass status to be highlighted GREEN.
Is this possible to achieve to in SQL using DB Mail and HTML formatting?
A few forums have stated that JavaScript may need to be used but I'm not sure if its possible to even us JS in SQL.
My code is below:
----------------------------------------------------------------------------
----------------------------------- Declare Variables ----------------------
----------------------------------------------------------------------------
Declare #email_body nvarchar(max)
Declare #email_profile_name nvarchar(max)
Declare #email_recipients nvarchar(max)
Declare #email_subject nvarchar(max)
Declare #tableHTML nvarchar(MAX) = ''
Declare #Style nvarchar(MAX) = ''
Declare #Textdate nvarchar(max)
DECLARE #crlf nvarchar = CHAR(13)+CHAR(10)
Declare #Server nvarchar(max)
----------------------------------------------------------------------------
--------------------------- Set Varriables (That should not change) --------
----------------------------------------------------------------------------
set #Server = ##SERVERNAME
set #Textdate = cast(getdate() as date)
Set #email_subject = #Textdate + ': Morning SQL Server Checks'
----------------------------------------------------------------------------
----------------------------------- Set Varriables (User Input) ------------
----------------------------------------------------------------------------
--Add other Email addresses as needed. Seperate with Semi-colon (;)
set #email_recipients = 'Email#Email.com'
----------------------------------------------------------------------------
----------------------------------- Create Temp Tables ---------------------
----------------------------------------------------------------------------
IF OBJECT_ID('tempdb..#Results') IS NOT NULL
DROP TABLE #Results
Create table #Results (
[Server] nvarchar(max),
[Entity] nvarchar(max),
[Status] nvarchar(max),
[Message] nvarchar(max),
[Type] nvarchar(max))
----------------------------------------------------------------------------
----------------------------------- Generate Data --------------------------
----------------------------------------------------------------------------
--Gets SQL Agent Results (Script Derived from here:
https://social.msdn.microsoft.com/Forums/sqlserver/en-US/534cc5be-0021-4766-
9eef-92fea819e2e3/script-to-get-sql-server-agent-job-schedule-and-the-last-
run-status?forum=sqldatabaseengine)
Insert into #Results
SELECT ##SERVERNAME as 'Server Name'
,J.Name AS 'Job Name'
--,CASE J.Enabled WHEN 1 THEN 'Yes' WHEN 0 THEN 'No' END as 'Job
Enabled'
,CASE WHEN LASTRUN.run_status = 0 THEN 'Failed'
WHEN LASTRUN.run_status = 1 THEN 'Succeeded'
WHEN LASTRUN.run_status = 2 THEN 'Retry'
WHEN LASTRUN.run_status = 3 THEN 'Cancelled'
ELSE 'Unknown' END as 'Last Run Status'
,LASTRUN.message as 'Last Run Message'
,'SQL Agent Jobs' as 'Type'
FROM msdb.dbo.sysjobs J LEFT OUTER JOIN msdb.dbo.sysjobschedules JS ON
J.job_id = JS.job_id
LEFT OUTER JOIN msdb.dbo.sysschedules S ON JS.schedule_id = S.schedule_id
LEFT OUTER JOIN (SELECT J1.job_id
,J1.RUN_DURATION
,J1.run_date
,J1.run_time
,J1.message
,J1.run_status
FROM msdb.dbo.sysjobhistory J1
WHERE instance_id = (SELECT MAX(instance_id)
FROM msdb.dbo.sysjobhistory J2
WHERE J2.job_id = J1.job_id)) LASTRUN ON J.job_id = LASTRUN.job_id
where J.Enabled = 1 --Only check for agents that have been enabled
--------------------------------------------------------------------------
----------------------------------- Generate Email -------------------------
----------------------------------------------------------------------------
--Set Style (CSS)
SET #Style += +N'<style type="text/css">' + N'.tg {border-
collapse:collapse;border-spacing:0;border-color:#aaa;}'
+ N'.tg td{font-family:Arial, sans-serif;font-size:14px;padding:10px 5px;border-style:solid;border-width:1px;overflow:hidden;word-break:normal;border-color:#aaa;color:#333;background-color:#fff;}'
+ N'.tg th{font-family:Arial, sans-serif;font-size:14px;font-weight:normal;padding:10px 5px;border-style:solid;border-width:1px;overflow:hidden;word-break:normal;border-color:#aaa;color:#fff;background-color:#f38630;}'
+ N'.tg .tg-9ajh{font-weight:bold;background-color:#68cbd0}' + N'.tg .tg-hgcj{font-weight:bold;text-align:center}'
+ N'</style>';
--Set Email Output (HTML Layout)
Set #tableHTML += #Style + #tableHTML + N'<H1 style="color:Blue;">' +
#Textdate + ': Morning SQL Server Checks</H1>' +
N'<H2>' + #Server + '</H2>' +
N'<H3>Databases</H3>' +
+ N'<table class="tg">' --DEFINE TABLE
-- Define Headers for Database Check
+ N'<tr>'
+ N'<H3>SQL Agents</H3>' +
+ N'<table class="tg">' --DEFINE TABLE
+ N'<tr>'
+ N'<td class="tg-9ajh">Server</td>'
+ N'<td class="tg-9ajh">Entity</td>'
+ N'<td class="tg-9ajh">Status</td>'
+ N'<td class="tg-9ajh">Message</td>'
+ N'<td class="tg-9ajh">Type</td></tr>'
-- Define data for SQL Agent and cast to xml
+ Cast((
Select td = isnull([Server],'###')
,''
,td = isnull([Entity],'###')
,''
,td = isnull([Status],'###')
,''
,td = isnull([Message],'###')
,''
,td = isnull([Type],'###')
,''
from #Results
where [type] = 'SQL Agent Jobs' FOR
XML PATH('tr') ,
TYPE
) AS NVARCHAR(MAX))
+ N'</table>';
-- Send the Email
EXEC msdb.dbo.sp_send_dbmail
#profile_name = 'Outlook Support Profile',
#recipients = #email_recipients,
#body = #tableHTML,
#body_format = 'HTML',
#subject = #email_subject
----------------------------------------------------------------------------
----------------------------------- Cleanup --------------------------------
----------------------------------------------------------------------------
drop table #Results
I hope the code is clear enough and makes sense.
Thanks you
Anthony
I do something similar with my dbmail audit emails to differentiate between production and non-production instances.
The method I use is to predefine the style information and then use a unique value in the body string to identify where the style needs to be applied. In your case the unique values we can use are <td>Failed and <td>Succeeded. By doing a replace on those values to a version that includes the style, you should get a table with your conditional formatting.
I made the following two changes to your script and ran it against one of my test instances. It looks like it should get you where you want.
First, update the style section:
--Set Style (CSS)
SET #Style += +N'<style type="text/css">' + N'.tg {border-
collapse:collapse;border-spacing:0;border-color:#aaa;}'
+ N'.tg .green{background-color: green; color:white;}'
+ N'.tg .red{background-color: red; color:white;}'
+ N'.tg td{font-family:Arial, sans-serif;font-size:14px;padding:10px 5px;border-style:solid;border-width:1px;overflow:hidden;word-break:normal;border-color:#aaa;color:#333;background-color:#fff;}'
+ N'.tg th{font-family:Arial, sans-serif;font-size:14px;font-weight:normal;padding:10px 5px;border-style:solid;border-width:1px;overflow:hidden;word-break:normal;border-color:#aaa;color:#fff;background-color:#f38630;}'
+ N'.tg .tg-9ajh{font-weight:bold;background-color:#68cbd0}' + N'.tg .tg-hgcj{font-weight:bold;text-align:center}'
+ N'</style>';
After #tableHTML is built, add a REPLACE to shove the style formatting into the generated table:
SELECT #tableHTML = REPLACE(REPLACE(#tableHTML,N'<td>Failed',N'<td class="Red">Failed'),N'<td>Succeeded',N'<td class="green">Succeeded')

SQL HTML email has no content but data is present in table

I am sending a HTML email that contains some rows from a table. I am using a temporary table #tableupdate which definitely has data in it when I run the script.
Everything runs fine and I get the email, it just has no content whatsoever. When I view the source of the email it's blank. Can anyone see where I have gone wrong?
To help diagnose the problem, I've been outputting the contents of the variable containing all the HTML in it at various points and it seems to be empty after this part:
select #tableHTML = #tableHTML + #body
+ '</table></div></body></html>'
#body doesn't seem to populate at all. I'm just not sure what to change to make it work.
The relevant piece of code, including comments to show where the data disappears:
select * from #tableupdate --rows are returned
declare #emailSubject varchar(100),
#textTitle varchar(100),
#tableHTML nvarchar(max)
select #textTitle = 'Test table'
set #tableHTML = '<html><head><style>' +
'td {border: solid black 1px;padding-left:5px;padding-right:5px;padding-top:1px;padding-bottom:1px;font-size:11pt;} ' +
'</style></head><body>'
+ '<div style="margin-top:20px; margin-left:5px; margin-bottom:15px; font-weight:bold; font-size:1.3em; font-family:tahoma;">' +
#textTitle + '</div>'
+ '<div style="margin-left:50px; font-family:tahoma;"><table cellpadding=0 cellspacing=0 border=0>' +
'<tr bgcolor=#4b6c9e>'
+ '<td align=center><font face="calibri" color=White><b>Col1</b></font></td>'
+ '<td align=center><font face="calibri" color=White><b>Col2</b></font></td>'
+ '<td align=center><font face="calibri" color=White><b>Col3</b></font></td>'
+ '<td align=center><font face="calibri" color=White><b>Col4</b></font></td>'
+ '<td align=center><font face="calibri" color=White><b>Col5</b></font></td>'
+
'</tr>'
select #tablehtml --has the correct value at this point
select #body =
(
select ROW_NUMBER() over(order by id) % 2 as TRRow,
td = col1,
td = col2,
td = col3,
td = col4,
td = col5
from #tableUpdate
where notificationType = 'NEWDATE'
order by clname
for XML raw('tr'), elements
)
select #body --empty?!
set #body = REPLACE(#body, '<td>', '<td align=center><font face="tahoma">')
set #body = REPLACE(#body, '</td>', '</font></td>')
set #body = REPLACE(#body, '_x0020_', space(1))
set #body = Replace(#body, '_x003D_', '=')
set #body = Replace(#body, '<tr><TRRow>0</TRRow>', '<tr bgcolor=#F8F8FD>')
set #body = Replace(#body, '<tr><TRRow>1</TRRow>', '<tr bgcolor=#EEEEF4>')
set #body = Replace(#body, '<TRRow>0</TRRow>', '')
select #body --still empty
select #tableHTML = #tableHTML + #body
+ '</table></div></body></html>'
select #tablehtml --now empty!
select #tableHTML = '<div style="color:Black; font-size:11pt; font-family:tahoma; width:100px;">' + #tableHTML + '</div>'
select #tableHTML --still empty
EXEC msdb.dbo.sp_send_dbmail
#profile_name = #databaseMailProfileName,
#body = #tableHTML,
#body_format ='HTML',
#recipients = 'me#me.com',
#subject = 'Subject' ;
If I simply pass select * from #tableupdate or similar to the email, it sends me the data in a not very nice format.
The issue is the query below, returns NULL.
select #body =
(
select ROW_NUMBER() over(order by id) % 2 as TRRow,
td = col1,
td = col2,
td = col3,
td = col4,
td = col5
from #tableUpdate
where notificationType = 'NEWDATE'
order by clname
for XML raw('tr'), elements
)
Focus on this single query, and you will solve your issue. Without sample data of #tableUpdate, we can't solve your problem. However, since #body is NULL, concatenating anything to it will also yield NULL.
For example, select 1 + null, 'this string' + null will return two NULLs.
Thus, all of these set operators will still yield NULL for #body
set #body = REPLACE(#body, '<td>', '<td align=center><font face="tahoma">')
set #body = REPLACE(#body, '</td>', '</font></td>')
set #body = REPLACE(#body, '_x0020_', space(1))
set #body = Replace(#body, '_x003D_', '=')
set #body = Replace(#body, '<tr><TRRow>0</TRRow>', '<tr bgcolor=#F8F8FD>')
set #body = Replace(#body, '<tr><TRRow>1</TRRow>', '<tr bgcolor=#EEEEF4>')
set #body = Replace(#body, '<TRRow>0</TRRow>', '')
select #body --still empty
Then, you set #tableHTML to NULL by concatenating it with #body because #body IS NULL
select #tableHTML = #tableHTML + #body
+ '</table></div></body></html>'
Which leaves #tableHTML and #body with the value of NULL.
A stab at fixing this, since you are building a table, would be to set #body like so:
select #body =
cast((select ROW_NUMBER() over(order by id) % 2 as 'td',
'',
isnull(col1,'') as 'td',
'',
isnull(col2,'') as 'td',
'',
isnull(col3,'') as 'td',
'',
isnull(col4,'') as 'td',
'',
isnull(col5,'') as 'td'
from #tableUpdate
where notificationType = 'NEWDATE'
order by clname
for XML path('tr'), elements) as nvarchar(max))

How to left align column entries in an email generated by SQL+HTML script

I am using SQL+HTML script to send an email containing top 5 columns of a table mytable. Currently, I have all the column titles aligned centrally and each column entries aligned to the right using [th] and [td] repsectively. How can I make entries in Vendor column left aligned while keeping everything else the same?
DECLARE #dt datetime, #prev_dt datetime
SELECT #dt = dbo.GetDateOnly(getdate())
SELECT #prev_dt = dbo.GetDateOnly(getdate()-1)
SELECT top 5
Vendor,
OUTL_New_$,
OUTL_Old_$,
Outl_Diff_$ ,
OUTL_Diff_Perc,
Analyst
into #vpositive
FROM mytable
ORDER BY 4 DESC
--select * from #vpositive
if(##ROWCOUNT>0)
begin
--drop table #email
DECLARE #Body2 varchar(max)
declare #TableHead2 varchar(max)
declare #TableTail varchar(max)
Set #TableTail = '</table></body></html>';
Set #TableHead2 = '<html><head>' +
'<hr style="height:1px;border:none;color:#333;background-color:#333;">'+
'<H5 style="color: #000000; font-family:Arial">2: VENDOR LEVEL TOP 5 OUTL $ <font color="blue">INCREMENTS -</font></H5>' +
'<style>' +
'td {border: solid black 1px;padding-left:5px;padding-right:5px;padding-top:1px;padding-bottom:1px;font-size:10pt;color:Black;text-align:right;font-family:Arial;} ' +
'th {border: solid black 1px;padding-left:5px;padding-right:5px;padding-top:1px;padding-bottom:1px;font-size:10pt;color:Black;text-align:center;font-family:Arial;} ' +
'</style>' +
'</head>' +
'<body><table cellpadding=0 cellspacing=0 border=0 width=auto>' +
'<tr bgcolor=#007336>'+
'<th><b><font color="white">Vendor</font></b></th>' +
'<th><b><font color="white">OUTL$ New</font></b></th>' +
'<th><b><font color="white">OUTL$ Old</font></b></th>' +
'<th><b><font color="white">OUTL$ Diff</font></b></th>' +
'<th><b><font color="white">OUTL$ Diff Perc</font></b></th>' +
'<th><b><font color="white">Analyst</font></b></th></tr>';
--Select information for the Report--
Select #Body2= (select
substring(Vendor,1,60) As [TD]
,'$ '+substring(parsename(convert(varchar,convert(money,cast(OUTL_New_$ as int)),1),2),1,13) As [TD]
,'$ '+substring(parsename(convert(varchar,convert(money,cast(OUTL_Old_$ as int)),1),2),1,13) As [TD]
,'$ '+substring(parsename(convert(varchar,convert(money,cast(OUTL_Diff_$ as int)),1),2),1,13) As [TD]
,substring(CAST(OUTL_Diff_Perc AS varchar(10)),1,4)+' %' As [TD]
,substring(Analyst,1,20) As [TD]
from #vpositive
For XML raw('tr'), Elements)
Set #Body = #TableHead2 + #Body2 + #TableTail
--Email
EXEC msdb.dbo.sp_send_dbmail
#recipients='abc#abc.com',
#subject = My analysis',
#body = #Body,
#body_format = 'HTML';
end
Did you try this:
<th align="left">
or this:
text-align: left;

sp_send_dbmail Incorrect syntax near '<'

I'm having a problem sending a HTML formatted email from SQL server.
With the following section of code I get a "Line 1, incorrect syntax near '<'" error.
SET #tableHTML =
'<H1>Progress Report</H1>' +
'<table border="1">' +
'<tr>' +
'<th>Project Name</th>' +
'<th>Platform</th>' +
'<th>Due By</th>' +
'<th>Current Status</th>' +
'<th>Current State</th>' +
'</tr>' +
CAST (
(
SELECT
td = [Project Name], ' ',
td = Platform, ' ',
td = [Due By], ' ',
td = [Current Status], ' ',
td = [Current State], ' '
FROM [dbo].[table_name]
ORDER BY [Current Status] DESC
FOR XML PATH('tr'), TYPE
) AS NVARCHAR(MAX) ) +
'</table>' ;
I cant seem to pin it to anything in particular? Any Idea's?
Thanks
Update 1:
Ok I've run the code in a debug session and have checked the contents of #tableHTML, the contents looks fine and it gets populated with the expected data from my Table.
Meaning the errors coming in from somewhere else, so I've copied the whole query this time.
DECLARE #tableHTML NVARCHAR(MAX);
SET #tableHTML =
'<h1>Progress Report</h1>' +
'<table border="1">' +
'<tr>' +
'<th>Project Name</th>' +
'<th>Platform</th>' +
'<th>Due By</th>' +
'<th>Current Status</th>' +
'<th>Current State</th>' +
'</tr>' +
CAST
(
(
SELECT
td = [Project Name], '',
td = Platform, '',
td = [Due By], '',
td = [Current Status], '',
td = [Current State], ''
FROM [dbo].[table_name]
ORDER BY [Current Status] DESC
FOR XML PATH('tr'), TYPE
) AS NVARCHAR(MAX) ) +
'</table>';
EXEC msdb.dbo.sp_send_dbmail
#profile_name = 'db_mail_account',
#recipients = 'example#example.com',
#subject = 'Daily Project Tracking Report',
#query = #tableHTML,
#body_format = 'HTML';
Thanks again.
It looks like you want #tableHTML to be the body of the email, but you're passing it in as #query, which has to contain valid SQL, hence the error.
Try using #body instead:
EXEC msdb.dbo.sp_send_dbmail
#profile_name = 'db_mail_account',
#recipients = 'example#example.com',
#subject = 'Daily Project Tracking Report',
#body = #tableHTML,
#body_format = 'HTML';

Adding Image on to send email thru SQL

I am trying to send a simple HTML email thru SQL stored procedure.
Is it possible adding a image such as company logo for the email result?
This is a part of stored procedure.
/*Create HTML*/
SET #TableHTML =
N'<H4>Production Alert (' + CONVERT(VARCHAR(10),GETDATE(),101) + ')</H4>' +
N'<table border="1">' +
N'<tr>' +
N' <td>Company</td>' +
N' <td width="70" align="CENTER">Department</td>' +
N' <td width="70" align="CENTER">Target</td>' +
N' <td width="70" align="CENTER">Shipped</td>' +
N' <td width="70" align="CENTER">Achievement by Yesterday</td>' +
N' <td width="70" align="CENTER">Achievement for this month</td>' +
N' <td width="70" align="CENTER">Difference</td>' +
N' <td width="70" align="CENTER">Catch Up QTY</td>' +
N'</tr>' +
CAST ( ( SELECT td = a.CompanyName, '', 'Right' AS "td/#align",
td = DepartmentName, '', 'Left' AS "td/#align",
td = ForecastQtyAcc, '', 'Right' AS "td/#align",
td = ShippedQtyAcc, '', 'Right' AS "td/#align",
td = ThePercentage, '', 'Right' AS "td/#align",
td = ThePercentageAll, '', 'Right' AS "td/#align",
td = TheDiff, '', 'Right' AS "td/#align",
td = CatchUpQTY, ''
FROM #Monthdata a
FOR XML PATH('tr'), TYPE
) AS NVARCHAR(MAX) ) +
N'</table>' ;
DROP TABLE #Monthdata
/Email it/
SET #TableHTML = #TableHTML +
N'' +
N''
See: Embed Images in emails created using SQL Server Database Mail