SQL Email based on query - sql

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)

Related

sp_send_dbmail - Assistance please

SQL newbie. I have several jobs sending query results via email, all working fine. I'm having trouble with this last one and am not sure what is wrong. The dbmailprofile works fine and the receipients are fine. The query works if I run it in SSMS but it doesn't work if I try to create a email job. I changed the #recipients to a generic term and change the query to not show anything specific. Any help is appreciated, thanks.
USE msdb
EXECUTE AS USER = 'dbo'
EXEC msdb.dbo.sp_send_dbmail
#profile_name = 'dbmailprofile',
#recipients = 'username#someone.com',
#query = ' SELECT A.DOCNUMBER as DocumentNumber,P.DOCNAME as DocumentName,A.TYPIST as UserSystemID,PP.USER_ID as UserID,PP.FULL_NAME as UserFullName,A.ACTIVITY_TYPE as ActivityCode,
AT.DESCRIPTION as ActivityDescription, CAST(DATEADD(mi, DATEDIFF(mi, GETUTCDATE(), GETDATE()), START_DATE) AS varchar(64))
AS 'ActivityTime In Local Time'
FROM DOCSADM.ACTIVITYLOG A
JOIN DOCSADM.PROFILE P
ON A.DOCNUMBER=P.DOCNUMBER
JOIN DOCSADM.PEOPLE PP
ON A.TYPIST=PP.SYSTEM_ID
JOIN DOCSADM.ACT_TYPES AT
ON A.ACTIVITY_TYPE=AT.VALUE
WHERE PP.USER_ID = 'USER'
AND A.START_DATE
> DATEADD(DD, -1,GETDATE())
GROUP BY A.DOCNUMBER,P.DOCNAME,A.TYPIST,PP.USER_ID,PP.FULL_NAME,
A.ACTIVITY_TYPE,AT.DESCRIPTION,A.START_DATE ORDER BY A.DOCNUMBER DESC, A.START_DATE DESC;',
#subject = 'Activity Report',
#body = 'The Stored Procedure completed sucessfully' ,
When I run this, I get the error 'Incorrect syntax near 'ActivityTime'

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 can I create a trigger for sending an email with an alert message that goes out the 1st and 16th of every month?

I'm pretty new to Microsoft SQL and am trying to create an alert that will send an email. This alert would be set up to run on the 1st and 16th of every month. I also want to have that persons supervisor and manager included in on the alert email.
My tables are:
User Table
UserID(pk), FirstName, LastName, GroupID(fk), Email
Group Table
ID(Pk), Supervisor(pk)
Balance Table Balance(PK)
to explain this:
User.GroupID = Group.ID
User.UserID = Group.Supervisor
I'm having a hard time creating a query to find the email of the user's supervisor.
here is my trigger for sending out an email:
CREATE OR REPLACE Trigger BalanceEmail
AFTER UPDATE ON Balance
FOR EACH ROW
DECLARE bal decimal(9,2);
DECLARE useremail varchar(50);
DECLARE supervisorEmail varchar(50);
DECLARE NAME varchar(10);
BEGIN
Select Balance
from BalanceTable
into bal
where userid = :new.userid;
Select Firstname, Lastname
From USER
into NAME
where userid = :new.userid;
select distinct(email)
from User
into useremail
where userid = :new.userid;
--- Can't figure out this query
---select distinct(email)
---from User
---into supervisorEmail
---where userid = :new.userid and G.supervisor = T.UserID;
IF Exists where bal > 200.00
BEGIN
EXEC
#Recipients = useremail
#Profile_name = 'Balance'
#subject = ' Balance over 200'
#body = (name + 'have accumulated' + bal + 'hours. Please contact your supervisor to schedule some time off.')
end if;
end;
How can I write a syntax for sending the email out on the 1st and 16th of every month?
I know I have a lot of errors right now, but please help and all is appreciated.
Dear me you are in a mess aren't you!
Firstly you need to improve your table structures. The Balance table is seems unnecessary, your Users table probably should have a balance column. See below for a better structure as I see it. The following is a script that sets a couple of tables:
CREATE TABLE UserTable (
UserID INT,
FirstName VARCHAR(100),
LastName VARCHAR(100),
GroupID INT,
Email VARCHAR(256),
Balance FLOAT
)
CREATE TABLE GroupTable (
GroupID INT,
GroupName VARCHAR(100),
GroupSupervisorID INT
)
Now populate the new tables with dummy data for testing:
INSERT GroupTable (GroupID, GroupName, GroupSupervisorID) VALUES(1, 'Group 1', 1)
INSERT GroupTable (GroupID, GroupName, GroupSupervisorID) VALUES(2, 'Group 2', 4)
INSERT UserTable (UserID, FirstName, LastName, GroupID, Email, Balance) VALUES(1, 'Anne', '', 1, 'Anne#someaddress.com', 0 )
INSERT UserTable (UserID, FirstName, LastName, GroupID, Email, Balance) VALUES(2, 'Suzy', '', 1, 'Suzy#someaddress.com', 250)
INSERT UserTable (UserID, FirstName, LastName, GroupID, Email, Balance) VALUES(3, 'Peta', '', 2, 'Peta#someaddress.com', 211)
INSERT UserTable (UserID, FirstName, LastName, GroupID, Email, Balance) VALUES(4, 'Lisa', '', 2, 'Lisa#someaddress.com', 66 )
As others have mentioned you need to set up a SQL SERVER Agent job that fires off on the 1st and 16th of every month. Secondly you need to set up your SQL SERVER to do emails, see this link for sp_send_dbmail
When your SQL Agent runs it should execute a script like the following:
DECLARE #UserId INT
DECLARE #UserEmailRecipient VARCHAR(256)
DECLARE #SupervisorEmailRecipient VARCHAR(256)
DECLARE #Name VARCHAR(256)
DECLARE #Balance FLOAT
DECLARE UserEmail_Cursor CURSOR
FOR
SELECT
UserID
FROM
UserTable
WHERE
Balance >= 200.00
OPEN UserEmail_Cursor;
FETCH NEXT FROM UserEmail_Cursor INTO #UserId
WHILE ##FETCH_STATUS = 0
BEGIN
SELECT
#Name = ut.FirstName + ' ' + ut.LastName,
#UserEmailRecipient = ut.Email,
#Balance = ut.Balance,
#SupervisorEmailRecipient = Supervisors.Email
FROM
UserTable AS ut
JOIN GroupTable AS gt
ON ut.GroupID = gt.GroupID
JOIN UserTable AS Supervisors
ON gt.GroupSupervisorID = Supervisors.UserID
WHERE
ut.UserID = #UserId
-- Send User email
EXEC msdb.dbo.sp_send_dbmail
#profile_name = 'DB Email Administrator', --NOTE THAT THIS MUST BE SET UP IT IS NOT SOME ARBITRARY STRING
#recipients = #UserEmailRecipient,
#body = #Name + ', you have accumulated' + CAST(#Balance AS VARCHAR(20)) + 'hours. Please contact your supervisor to schedule some time off.',
#subject = 'Balance over 200' ;
-- Send Supervisor email
EXEC msdb.dbo.sp_send_dbmail
#profile_name = 'DB Email Administrator', --NOTE THAT THIS MUST BE SET UP IT IS NOT SOME ARBITRARY STRING
#recipients = #SupervisorEmailRecipient,
#body = 'One of your minions, ' + #Name + 'has accumulated' + CAST(#Balance AS VARCHAR(20)) + 'hours. She will contact you to schedule some time off.',
#subject = 'Balance over 200' ;
FETCH NEXT FROM UserEmail_Cursor INTO #UserId;
END;
CLOSE UserEmail_Cursor;
DEALLOCATE UserEmail_Cursor;
GO
If you have correctly set up db mail and the agent job the above script will send an email to each user and their suprvisor advising of their balance.

use a "temporary table" and "while loop" together in sql

I want to create a table and after that use the table information in a while loop. I had been used 'with' to create the table but my code has error. The code comes below:
declare #i integer
set #i=0;
with cte as
(SELECT ROW_NUMBER()OVER(ORDER BY ItemID) as RowNumber,*,DATEDIFF(day,GETDATE(),AdDateTo)as DaysToExpire
FROM KenticoCMS1.dbo.AD_Advertise inner join KenticoCMS1.dbo.CMS_User
ON KenticoCMS1.dbo.AD_Advertise.ItemCreatedBy = KenticoCMS1.dbo.CMS_User.UserID
WHERE DATEDIFF(day,GETDATE(),AdDateTo) in (SELECT RemainDays FROM KenticoCMS1.dbo.AD_SendEmailForExpire)
AND AdShow=1)
--SELECT * FROM cte
while ( #i<=(select max(RowNumber) from cte))
BEGIN
#i=#i+1;
EXEC msdb.dbo.sp_send_dbmail #profile_name='ExpireAdvertiseEmail',
#recipients= select Email FROM cte where RowNumber=#i , --'mj.yazdani1988#gmail.com',
#subject='Test message',
#body='This is the body of the test message.Congrates Database Mail Received By you Successfully.'
END
GO
and my error:
Msg 156, Level 15, State 1, Line 13
Incorrect syntax near the keyword 'while'.
Msg 156, Level 15, State 1, Line 16
Incorrect syntax near the keyword 'select'.
Msg 102, Level 15, State 1, Line 16
Incorrect syntax near ','.
You cannot use CTE as temporary table. You could create table (or declare table variable), put your data there and do your work:
create table #temp (RowNumber int, Email nvarchar(max)
But so far looks like your code could be changed like this:
declare #Email nvarchar(max)
declare cur cursor local fast_forward for
select
u.Email
from KenticoCMS1.dbo.AD_Advertise as a
inner join KenticoCMS1.dbo.CMS_User as u on u.UserID = a.ItemCreatedBy
where
a.AdShow = 1 and
datediff(day, getdate(), a.AdDateTo) in
(
select t.RemainDays
from KenticoCMS1.dbo.AD_SendEmailForExpire as t
)
open cur
while 1 = 1
begin
fetch cur into #Email
if ##fetch_status <> 0 break
exec msdb.dbo.sp_send_dbmail
#profile_name = 'ExpireAdvertiseEmail',
#recipients = #Email,
#subject = 'Test message',
#body = 'This is the body of the test message.Congrates Database Mail Received By you Successfully.'
end
close cur
deallocate cur
Note table aliases, removing redundant brackets. I think it'll also helps to remove datediff, but have to see your data before.
try this: put this part
while ( #i<=(select max(RowNumber) from cte))
BEGIN
#i=#i+1;
EXEC msdb.dbo.sp_send_dbmail #profile_name='ExpireAdvertiseEmail',
#recipients= (
before
with cte as
and a
)
after
...where RowNumber=#i
for my understanding the cte definition must be followed directly by select (and it can be used in only that one select that follows)
hope it helps...
EDIT: commas obviously part of parameterlist for function