I am trying to send 2 different tables inside of 1 email. I want one table to establish data concerning data stored in 1 database and the other table for a second database of information. I can produce 1 email simply enough but i cannot understand how to set a second table with a completely different query and data in the same email.
here is what i am currently working with:
USE MY DATABASE
DECLARE
#tableHTML NVARCHAR(MAX)
SET #tableHTML =
N'<H1>Lacrosse Inquiries</H1>' +
N'<table border="1" style="text-align: middle;" width:100% height:20px style="cell" cellspacing="0" cellpadding="5">' +
N'<tr><th>FIRST NAME</th><th>LAST NAME</th><th>Entry Term</th></th><th>Market Segment</th><th>State</th><th>Home Number</th><th>Cell Phone</th>'+
CAST ( ( SELECT td = INQUIRY.F_NAME , ''
, td = INQUIRY.L_NAME , ''
, td = INQUIRY.ENTRY_TERM , ''
, td = INQUIRY.MARKET_SEG , ''
, td = EWADDRESS.STATE , ''
, td = EWADDRESS.HOME_PHONE , ''
, td = EWADDRESS.WORK_PHONE , ''
from EWSTUDENT AS INQUIRY inner join EWMULTI1M as sport on sport.EWSTUID=INQUIRY.EWSTUID left JOIN EWADDRESS ON EWADDRESS.EWSTUID=INQUIRY.EWSTUID LEFT JOIN ESTUDENT ON ESTUDENT.EWSTUID=INQUIRY.EWSTUID
where VCODETYPE = 'EACTIV1M' AND VCODE ='CLAX' AND INQUIRY.GENDER = 'F' AND STUD_TYPE ='P' and (CONVERT(VARCHAR(8), sport.CREATE_DT, 112) = CONVERT(varchar(8), GETDATE(), 112))
order by INQUIRY.L_NAME
FOR XML PATH('tr'), TYPE
) AS NVARCHAR(MAX) ) +
N'</table>' ;
EXEC msdb.dbo.sp_send_dbmail
#profile_name= 'Jordan.Sorensen',
#recipients = 'Jordan.sorensen#svu.edu',
#from_address = 'Jordan.Sorensen#svu.edu',
#body = #tableHTML,
#execute_query_database= 'MY DATABASE',
#subject ='Womens Lacrosse Inquiries',
#body_format= 'HTML'
GO
ANY SUGGESTIONS ON HOW TO CREATE TWO DIFFERENT TABLES WITH TWO COMPLETELY DIFFERENT SETS OF DATA IN ONE EMAIL?
FOR XML PATH('tr'), TYPE
) AS NVARCHAR(MAX) ) +
N'</table>' --<-- This is where you 1st query ends add a couple of line breaks
+ N'<br/><br/>' -- and add you second table just like you have done before
+ N'<table border="1" style="text-align: middle;" width:100% height:20px style="cell" cellspacing="0" cellpadding="5">'
+ N'<tr><th>FIRST NAME</th><th>LAST NAME</th><th>Entry Term</th></th><th>Market Segment</th><th>State</th><th>Home Number</th><th>Cell Phone</th>'
+ CAST ( (/*Your Select just like you have done for 1st table*/) AS NVARCHAR(MAX))
+ N'</table>'
Obviously HTML generated from both sql queries are concatenated and set the value to variable #tableHTML, the rest of the stuff remains the same passing parameters to your procedure and etc etc.
Related
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')
I am emailing an HTML table to users but I want to alias the hyperlinks for space reasons. Please have a look on the image.
Here is the Sample1 of the image:
Please see my below code :
DECLARE #bodyMsg nvarchar(max)
DECLARE #subject nvarchar(max)
DECLARE #tableHTML nvarchar(max)
SET #subject = 'Query Results in HTML with CSS'
DECLARE #email_to_notify nvarchar(256);
SELECT #email_to_notify = 'bens#ioec.co.za' ;
SET #tableHTML =
N'<style type="text/css">
...
</tr>' +
CAST ( (
SELECT
td = y.Customer,'',
td = y.ContractNumber,'',
td = y.Description ,'',
td = y.Market ,'',
td = y.BDM ,'',
td = y.EC ,'',
td = y.Reason ,'',
td = y.Link
FROM (SELECT FileReference AS 'Reference', Name AS 'Customer' ,
CASE WHEN ContractNumber IS NULL THEN '' ELSE ContractNumber END AS 'ContractNumber',
'http://gateway.ioec.co.za/#/trade/files/' + CONVERT(varchar(10),Gw_File.FileID) AS 'Link'
FROM Gw_File INNER JOIN ... ) y
FOR XML PATH('tr'), TYPE
) AS NVARCHAR(MAX) ) +
N'</table>'
EXEC msdb.dbo.sp_send_dbmail #recipients='rajivs#ioec.co.za',
#subject = #subject,
#body = #tableHTML,
#body_format = 'HTML' ;
I would also like to highlight rows depending on value of the reason column.
It seems like that when you're passing your markup, you aren't retaining it's type. Special characters, such as < will be replaced with a string representation to keep the xml valid. For example < & < and & & &.
If it's just the > and < symbols you can use a replace before sending out the email:
SET #tableHTML = REPLACE(REPLACE(#tableHTML,'>','<'),'<','>');
This however, trusts you have no nested HTML.
I am using html code in my SQL Script to output results from a table in an email, but I need to change the color of the text if any of the results come back as specific string. Here is a snippet of what I'm using to produce the table:
'<table border="2">' +
'<tr>
<th>No#</th>
<th>SERVER NAME</th>
<th>SERVER IP</th>
<th>STATUS </th>
</tr>' +
CAST (( SELECT DISTINCT
td = [NUMBER], '',
td = [SERVER NAME], '',
td = [SERVER IP], '',
td = [STATUS], ''
FROM SUMMARY
FOR XML PATH('tr'), TYPE
) AS VARCHAR(MAX) ) +
'</table>';
So I am concerned about the "STATUS" Field, if it comes back SUCCESS it could stay as regular text, if it says BAD then I want it to be Red.... I have tried putting in the <font color=""> tag but it only changes the Headers (between the TH tags)..
No# SERVER NAME SERVER IP STATUS
1 SERVER1 10.10.10.1 BAD --this should be red
2 SERVER2 10.10.10.2 SUCCESS
3 SERVER3 10.10.10.3 BAD --this should be red
4 SERVER4 10.10.10.4 SUCCESS
Like the commenter noted, you should really not be doing this. If you really want to, you will need to do it outside the query, since SQL will treat all query data as text and escape the HTML characters in order to display them as text.
A simple (but "ugly-ish") solution is to simply do a replace like this:
REPLACE('<table border="2">' +
'<tr>
<th>No#</th>
<th>SERVER NAME</th>
<th>SERVER IP</th>
<th>STATUS </th>
</tr>' +
CAST (( SELECT DISTINCT
td = [NUMBER], '',
td = [SERVER NAME], '',
td = [SERVER IP], '',
td = [STATUS], ''
FROM SUMMARY
FOR XML PATH('tr'), TYPE
) AS VARCHAR(MAX) ) +
'</table>', '>BAD<', '><font color="red">BAD</font><')
I am creating a report to be send out daily. In one of the columns I have String of all of the Item numbers associated with the Sales Order (So one sales order to possibly multiple Item numbers). The Item numbers String is separated by ','s. To be able to do this I am using a Select statement where Order numbers are same, for XML PATH('') inside of a STUFF.
After I have generated this temp table of my data I am sending an email of the data out. I am using HTML formatting in a #mailmsg setting up the table and sending it. My problem is when the email is sent the column with all of the Item numbers are all on the same line and I need them to be soft returned onto a new line (but same cell).
I have attempted to use CHAR(10) and CHAR(13) in my STUFF function to no prevail.
Any suggestions? Below is my code for my stuff into my temp table:
UPDATE #SOTable
Set PODetails = STUFF( (
Select ', PONumber: ' + CAST(PONum AS VARCHAR),
', POQty: ' + CAST(POQty AS VARCHAR)
From #POTable
Where SONo = PONo
FOR XML PATH('')
),1, 1, '')
Then for my mail message, after I populate the table headers do this for the data:
CAST ((
select
(convert(varchar(8), SO.SONum)) as [TD align=center], '',
(CONVERT(varchar(8), SO.SOItmNo)) as [TD align=center], '',
td = (ltrim(rtrim(SO.SODesc))), '',
(convert(varchar(8), SO.SONSN)) as [TD align=center], '',
CONVERT(varchar(8), SO.SOSRNo)as [TD align=center], '',
convert(varchar(3), SO.SOSRQty)as [TD align=center], '',
convert(varchar(3), SO.SOUOM)as [TD align=center], '',
CAST(convert(varchar, SO.SODate, 101) AS VARCHAR) as [TD align=center], '',
td = SO.PODetails
from #SOTable SO
order by SO.SODate
for XML RAW('tr'), ELEMENTS
) as nvarchar(max))
Check out my blog entry on database mail and different calls.
The key is setting the format to HTML
#body_format = 'HTML' ;
Here is a code snippet using Adventure works to create a HTML table.
If you still have questions, write back.
John
Code Snippet
-- Send with embedded html table containing query data
DECLARE #VAR_HTML NVARCHAR(MAX) ;
SET #VAR_HTML =
N'<h1>Work Order Report<h1>' +
N'<table border="1">' +
N'<tbody><tr><th>Work Order ID</th><th>Product ID</th>' +
N'<th>Name</th><th>Order Qty</th><th>Due Date</th>' +
N'<th>Expected Revenue</th></tr>' +
CAST ( ( SELECT td = wo.WorkOrderID, '',
td = p.ProductID, '',
td = p.Name, '',
td = wo.OrderQty, '',
td = wo.DueDate, '',
td = (p.ListPrice - p.StandardCost) * wo.OrderQty
FROM AdventureWorks2008R2.Production.WorkOrder as wo
JOIN AdventureWorks2008R2.Production.Product AS p
ON wo.ProductID = p.ProductID
WHERE DueDate > '2006-04-30'
AND DATEDIFF(dd, '2006-04-30', DueDate) < 2
ORDER BY DueDate ASC,
(p.ListPrice - p.StandardCost) * wo.OrderQty DESC
FOR XML PATH('tr'), TYPE
) AS NVARCHAR(MAX) ) +
N'</tbody></table>'
EXEC msdb.dbo.sp_send_dbmail
#recipients='john#craftydba.com',
#subject = 'Work Order List',
#body = #VAR_HTML,
#body_format = 'HTML' ;
I have been able to generate reports by creating tables holding results of sql queries and sending periodic emails. I am now required to combine some of them into one and am having a hard time getting it to work. A single table works but two tables results in a blank email.
DECLARE #TITLE NVARCHAR(MAX)
DECLARE #BODY NVARCHAR(MAX)
DECLARE #TITLE2 NVARCHAR(MAX)
DECLARE #BODY2 NVARCHAR(MAX)
DECLARE #SECTABLE NVARCHAR(MAX)
SET #TITLE =CAST((SELECT DISTINCT A.CLIENTPROJ as 'td','', A.CLIENTKEY as 'td','',
A.APIBOX as 'td','', A.ID as 'td', '',
COUNT(B.QUERYTERMS) as 'td', ''
FROM Clients AS A INNER JOIN QueryData AS B ON A.clientKey = B.clientKey
WHERE A.Id='0001000'
group by A.clientProj, A.clientkey, A.APIBox, A.ID order by
COUNT(B.QUERYTERMS) desc
FOR XML PATH ('tr'), ELEMENTS XSINIL) AS NVARCHAR(MAX))
SET #BODY = '<html><body><H4>QUERY ACTIVITY</H4>
<H5>CLIENT ID - 0001000</H5>
<table border = 2>
<tr>
<th> CLIENT NAME </th> <th> CLIENT KEY </th> <th> API FEED </th>
<th> CLIENT ID </th> <th> TOTAL QUERIES </th></tr>'
SET #BODY = #BODY + #TITLE + '</TABLE></BODY></HTML>'
EXEC msdb.dbo.sp_send_dbmail #profile_name='ME Admin',
#recipients = 'YAHOO#WOOHOO.com',
#subject = 'CLIENT QUERY REPORT',
#body = #BODY,
#body_format = 'HTML';
Not sure how and where to include the following second query:
SET #TITLE2 =CAST((SELECT DISTINCT B.CLIENTPROJ as 'td','',
B.CLIENTKEY as 'td','', B.apiBOX as 'td','', B.ID as 'td', '',
COUNT(A.QUERYTERMS) as 'td', ''
FROM QUERYDATA AS A RIGHT JOIN CLIENTS AS B ON
A.clientKey = B.clientKey WHERE A.Id='0001000' AND A.clientKey
IS NULL
group by B.clientProj, B.clientkey, B.APIBox, B.ID order by
COUNT(A.QUERYTERMS) desc
FOR XML PATH ('tr'), ELEMENTS XSINIL) AS NVARCHAR(MAX))
SET #BODY2 = '<html><body><H4>QUERY INACTIVITY</H4>
<H5>CLIENT ID - 0001000</H5>
<table border = 2>
<tr>
<th> CLIENT NAME </th> <th> CLIENT KEY </th> <th> API FEED</th>
<th>CLIENT ID </th> <th> TOTAL QUERIES </th></tr>'
I need both tables to appear in the body of the email and I am not sure how to integrate this.Any ideas appreciated.
final set statement
SET #TITLE = ....
SET #BODY = 'QUERY ACTIVITY
....'
SET #TITLE2 = ...//SECOND TABLE CONTENTS
SET #BODY2 = '<html><body><H4>QUERY INACTIVITY</H4>
<H5>....</tr>'
SET #BODY2 = #BODY + #BODY2 + #TITLE2 + '</TABLE></BODY></HTML>'