SQL Server Agent - sending emails with no content - sql

I have a query below which tells me if something is due in the next 24 hours, however using SQL Server Agent, it sends an email whether the query returns a result or not, so:
My Question
based on the SQL Code below which I will add directly into an SQL Agent Job, can i set it up to not send an email of the query returns a 0 row count?
I have done some research however applying a boolean doesnt work to detect if there are results or not, or I may have done it wrong:
Code
DECLARE #xml NVARCHAR(MAX)
DECLARE #body NVARCHAR(MAX)
SET #xml = CAST((
SELECT
Jobs.JobID AS 'td', '' ,
Jobs.JobName AS 'td', '',
ToDoList.List AS 'td', '',
Staff.StaffName AS 'td', '',
CONVERT(DATE, ToDoItem.DueDate) AS 'td', '',
ToDoItem.Comment AS 'td', ''
FROM ToDoItem
INNER JOIN Staff ON ToDoList.StaffID= Staff.StaffID
INNER JOIN ToDoList on ToDoItem.ToDoListID = ToDoList.ToDoListID
INNER JOIN JobSummaryAndStatus ON ToDoList.JSASID = JobSummaryAndStatus.JSASID
INNER JOIN Jobs ON ProjectSummaryAndStatus.JobID= Jobs.JobID
WHERE DueDate BETWEEN GETDATE() AND GETDATE() + 1
AND Staff.StaffID = 20
FOR XML PATH('tr'), ELEMENTS ) AS NVARCHAR(MAX))
SET #body ='<html><body><H3>Jobs Due Today</H3>
<table border = 1>
<tr>
<th> Job Ref </th> <th> JobName </th> <th> List Name </th> <th> Staff Name </th> <th> Due Date </th> <th> Comments </th></tr>'
SET #body = #body + #xml +'</table></body></html>'
EXEC msdb.dbo.sp_send_dbmail
#body = #body,
#body_format ='HTML',
#recipients = 'myemail#domain.com;',
#subject = 'Jobs Due Today';
Research
I tried this with little success so hopefully its my SQL Knowledge which is the reason why i cant apply this simple boolean checker. Im sure it would check the #body tag at the bottom before it sends the email and I could and in a IF statement of sorts here
http://www.sqlservercentral.com/Forums/Topic1131198-391-1.aspx
thanks for the help

If there isn't any result from the query the #xml variable should be empty so you should be able to check that:
if (len(#xml) > 0)
begin
EXEC msdb.dbo.sp_send_dbmail
#body = #body,
#body_format ='HTML',
#recipients = 'myemail#domain.com;',
#subject = 'Jobs Due Today';
end
I haven't tried it though.

Related

Obtain a repeated data and send SQL mail

Good day I have a table called Ticket which has several tickets registered, each one has a status:
1 = Accepted,2 = Assigned,3 = At ​​attention,4 = Attended,5 = Agree.
I want to perform a stored procedure in which I only send mail to the tickets that are in state 4, that is, my ticket has status 4, it is activated exec sp_sendmail .
Then I will use it as a Job every 30 minutes, check to see if it is still in that state and if it is in state 4 it sends again mail, once it changes state 4 to 5 it will not send anything and it will be closed.
Something like this, that loops through the list of tickets and sends an email. Couple notes, though: first, if you try to send too many at once, your email provider may start dropping them, so maybe put in a {pre}WAITFOR DELAY '00:00:02'{pre} delay between messages. Also, instead of sending one email per ticket, you can look into the query options in sp_send_dbmail: you can email a single list of all currently-4 tickets. It just depends on your needs.
CREATE PROCEDURE dbo.SendTicketAttendedEmails
AS
BEGIN
DECLARE #MailList TABLE(TicketID INT, SendTo VARCHAR(255))
DECLARE #ThisTicketID INT
, #MailMessage NVARCHAR(2000)
, #MailSubject NVARCHAR(255)
, #SendTo VARCHAR(255)
INSERT INTO #MailList
([TicketID], [SendTo])
SELECT t.[ID], u.[UserEmail]
FROM dbo.YourTicketTable t
JOIN dbo.YourUserTable u
ON t.UserCreated = u.ID
WHERE [StatusID] = 4
WHILE EXISTS(SELECT 1 FROM #MailList)
BEGIN
SELECT TOP(1) #ThisTicketID = [TicketID]
, #MailSubject = 'Ticket ' + CAST([TicketID] AS VARCHAR(10)) + ' is in status 4.'
, #MailMessage = 'Please review, or whatever, ticket ' + CAST([TicketID] AS VARCHAR(10)) + '.'
, #SendTo = COALESCE([SendTo], 'yourEmailAddress#InCase.Missing')
FROM #MailList
ORDER BY [TicketID];
DECLARE #mailitem_id INT ;
EXEC [msdb].dbo.[sp_send_dbmail]
#profile_name = 'SomeDBMailProfileName' -- sysname
, #recipients = #SendTo -- varchar(max)
, #subject = #MailSubject -- nvarchar(255)
, #body = #MailMessage -- nvarchar(max)
, #mailitem_id = #mailitem_id OUTPUT -- int
, #from_address = 'you#you.com' -- varchar(max)
, #reply_to = 'you#you.com' -- varchar(max)
DELETE #MailList
WHERE [TicketID] = #ThisTicketID
END
END
Basically you will use something like this for your job.
exec sp_send_dbmail
#profile_name = 'your_mail_profile'
,#recipients = 'you#email.com'
,#subject = 'Attended'
,#query = 'select * from yourTable where [status] = 4'
--,#attach_query_result_as_file = 1
--,#query_attachment_filename = 'somefile.csv'
See other options in the docs... and adjust accordingly.

SQL Server 2008 R2 match counts

I have a SQL query that checks when a stored procedure was last run, from that date it gathers all the units that were purchased between that date and today's date and compares it to another number. If they match it sends an email saying the two number match and executes the rest of the stored procedure. However, when it runs I constantly get 0 for the number of accounts, when it should be a value greater than 0 daily:Here is my code:
DECLARE #UnitsPurchased int
DECLARE #WelcomeLetterGenerated int
DECLARE #LastSuccesfulRunTime datetime
SET #LastSuccesfulRunTime = (select cast(run_datetime as DATE) from apsllc_v2.dbo.LastSuccesfulRunDate)
SET #UnitsPurchased = (SELECT COUNT(*) FROM rsbi.dbo.loans as l
where rsbi.dbo.fn_Convert_Paradata_Birth_Date(l.Unit_PURDATE) between #LastSuccesfulRunTime
AND getDate() and l.LN_CLASS in (58,59)) -- Shows the number of units that were purchased yesterday
SET #WelcomeLetterGenerated = ( SELECT COUNT(*) FROM apsllc_v2.dbo.ApsUpload ap where ap.FormNumber IN(1100,1150) ) -- Shows how many welcome letters were generated today
if #UnitsPurchased <> #WelcomeLetterGenerated
begin
EXEC msdb.dbo.sp_send_dbmail
#recipients = N''
, #body = ' '
, #subject = 'Welcome Letter Counts do not Match'
, #profile_name = 'Email_Profile_01'
return
end
ELSE if #UnitsPurchased = #WelcomeLetterGenerated --or if
begin
EXEC msdb.dbo.sp_send_dbmail
#recipients = N''
, #body = ' '
, #subject = 'Welcome Letter Counts Match'
, #profile_name = 'Email_Profile_01'
end

How to Execute the sql statement from a table and convert into html

Declare #a varchar(max)
Declare #b varchar(max)
set #a = cast((
SELECT td = f1, '', td = f2 , '' from tablenme Where f2 is null order by f1
for XML PATH('tr'), ELEMENTS )AS nvarchar(max))
set #b ='<html>
<body>
<H3>Stayed on the list</H3>
<table border = 1>
<tr bgcolor="#BBFFFF">
<th> f1 </th>
<th> f2 </th>
</tr> '
set #b = #b + #a +'</table></body></html>'
Print #b
I want to get the total select stmt used in above code from a table field.
`SELECT td = f1, '', td = f2 , '' from tablenme Where f2 is null order by f1`
I want to store the sql stmnt in a table field.
I have tried like this
Declare #a varchar(max)
Declare #b varchar(max)
Declare #c varchar(max)
Declare #sql varchar(max)
set #a = 'cast(('
set #sql=(SELECT sql_query from table2) -- I have stored total sql query in a field of table2
set #c = (' for XML PATH('tr'), ELEMENTS )AS nvarchar(max))')
set #b ='<html>
<body>
<H3>Stayed on the list</H3>
<table border = 1>
<tr bgcolor="#BBFFFF">
<th> f1 </th>
<th> f2 </th>
</tr> '
set #abc= #a+#sql+#c
set #b = #b + #a +'</table></body></html>'
Print #b
But here #abc is taking as string, it is not executing!.
I do not know if this helps you but...
once upon a time, I needed to send the query result as an html table in email body. I prepared myself a script that may not be the best but you do not have to change it a lot to make it work on any query you want.
Just bare in mind that if exists query must be the same that your actual query for html table, and that abstract query that list headers must have the same number of columns that your query (that is lame, i know. I could have query into temp table and ask information schema for column names but i was satisfied with what i get and did not want to spend more time on this)
declare #table xml
if exists ( select top 3 status,
name,
createdate
from sys.sysusers
where altuid = 1 )
begin
--CAUTION!
--query that creates table headers and query that creates content must have the same number of fields
--create table with data
set #table = ( --table formating
select '1' as '#border',
'3' as '#cellpadding',
'0' as '#cellspacing',
( --table header formating
select 'center' as '#align',
'font-weight: bold; background-color:silver' as '#style',
( --abstract entry with table headers
select 1 as Tag,
null as Parent,
'status' as [tr!1!td!element],
'name' as [tr!1!td!element],
'createdate' as [tr!1!td!element]
for xml explicit,
type
)
for xml path('tbody'),
type
),
( --actual query
select top 3
1 as Tag,
null as Parent,
status as [tr!1!td!element],
name as [tr!1!td!element],
convert(nvarchar(19), createdate, 120) as [tr!1!td!element]
from sys.sysusers
where altuid = 1
for xml explicit,
type
)
for xml path('table')
)
end
select #table
that will give you nice html table script like below
<table border="1" cellpadding="3" cellspacing="0">
<tbody align="center" style="font-weight: bold; background-color:silver">
<tr>
<td>status</td>
<td>name</td>
<td>createdate</td>
</tr>
</tbody>
<tr>
<td>0</td>
<td>public</td>
<td>2003-04-08 09:10:42</td>
</tr>
<tr>
<td>0</td>
<td>db_owner</td>
<td>2003-04-08 09:10:42</td>
</tr>
<tr>
<td>0</td>
<td>db_accessadmin</td>
<td>2003-04-08 09:10:42</td>
</tr>
</table>
you can change #table type from xml to varchar and then simply add some extra oppening and closing html tags you need.
take care

SQL Email based on query

I have set up SQL server to email and have successfully. I am trying to send an email with the following query:
select count(*) from report queue
I would like an email sent when count is > 10.
I have never done a SQL stored procedure before.
SELECT COUNT(*) AS ct
FROM report_queue
HAVING ct > 10
Can you try this?
select email from report queue group by email having count(*)>10
Another alternative;
IF ((SELECT COUNT(*) FROM [report queue]) > 10)
SELECT * FROM [report queue]
CREATE PROCEDURE [dbo].[email_report] (#recipients nvarchar(max), #subject nvarchar(max) = '', #body nvarchar(max) = '')
AS
BEGIN
IF (SELECT COUNT(*) FROM [report_queue]) > 10
EXEC [msdb].[dbo].[sp_send_dbmail]
#recipients = #recipients,
#subject = #subject,
#body = #body;
END
More details available here: sp_send_dbmail (Transact-SQL)

Select Values based on Range Automatically and Trigger Email

The table from which a data range is to be queried :
Id Variance
1 2
2 17
3 7
4 4
5 20
6 1
7 111
8 8
9 18
10 67
Another table that has
Freq StartRange EndRange
H 10 7
H 8 8
H 6 20
The data in the first table is loaded every 30mins through an SSIS package.
Now I want alert as in emails to be triggered when the data in the Variance column falls in the StartRange and EndRange.
CREATE PROCEDURE [dbo].[SP_Email] #Start varchar(50),#End varchar(50),#Date datetime
AS
BEGIN
DECLARE #xml NVARCHAR(MAX)
DECLARE #body NVARCHAR(MAX)
SET #xml = CAST(( SELECT [SlNo] AS 'td','',[date] AS 'td','',
[lag] AS 'td','', Percent AS 'td'
FROM TestTbl
WHERE(percent >= #Start AND percent < #End)
AND CAST(CONVERT(VARCHAR,curDate,106) AS DATETIME) = CAST(#Date AS DATETIME)
ORDER BY SlNo
FOR XML PATH('tr'), ELEMENTS ) AS NVARCHAR(MAX))
SET #body ='<html><body><H3>Report</H3>
<table border = 1>
<tr>
<th> SlNo </th> <th> date </th> <th> lag </th> <th> Percent </th></tr>'
SET #body = #body + #xml +'</table></body></html>'
EXEC msdb.dbo.sp_send_dbmail
#profile_name = 'Alert',
#body = #body,
#body_format ='HTML',
#recipients = 'abc#gmail.com'
#subject = 'Report';
END
Please suggest a process that will help me setup such in SQL Server 2005.
Thanks in Advance
This can be done via SQL Server Agent jobs:
EXEC dbo.sp_add_job
#job_name = N'Variance Check',
#notify_email_operator_name='you#your.domain',
#notify_level_email=2; -- Only notify you when YourStoredProceedure fails
GO
EXEC sp_add_jobstep
#job_name = N'Variance Check',
#step_name = N'Check the variance',
#subsystem = N'TSQL',
#command = N'EXEC YourStoredProceedure',
#retry_attempts = 1,
#retry_interval = 5 ;
GO
EXEC dbo.sp_add_schedule
#schedule_name = N'EveryThirtyMinutes',
#freq_type = 4, -- Daily
#freq_subday_type = 0x4, -- Minutes
#freq_subday_interval = 30,
#active_start_time = NULL; -- Start right away
USE msdb ;
GO
EXEC sp_attach_schedule
#job_name = N'Variance Check',
#schedule_name = N'EveryThirtyMinutes';
GO
EXEC dbo.sp_add_jobserver
#job_name = N'Variance Check';
GO
One way to approach this is through triggers. However, I don't recomment sending emails through triggers.
Instead, add a step to the process that loads the data in T1. After this step, call a stored procedure that finds the rows that meet the conditions and send the appropriate email.
It is rather hard to tell exactly what the conditions are, however. Your second table has three ranges. It is not clear which to apply to which row.