I am fairly new to doing more involved SQL work.
My goal is to email using the results of a query to drive email creation. I intend to create a stored procedure and schedule this twice a week (there will be at most 20 emails, this will not be heavy email load) on SQL Server 2008.
SELECT ProjectCodes.ProjectCode, COUNT(Projects.ProjectsID), ProjectApprovers.EmailApprover
FROM Projects
INNER JOIN ProjectCodes
ON Projects.ProjectCodesID=ProjectCodes.ProjectCodesID
INNER JOIN ProjectApprovers
ON Projects.ProjectCodesID=ProjectApprovers.ProjectCodesID
WHERE ProjectApprovers.IsPrimaryApprover=1
group by ProjectCodes.ProjectCode, ProjectApprovers.EmailApprover
This returns something similar to:
+-------------+-------+--------------+
| ProjectCode | Count | EmailAddress |
+-------------+-------+--------------+
| Code1 | 4 | Email1 |
| Code2 | 2 | Email2 |
| Code3 | 2 | Email3 |
| Code4 | 3 | Email4 |
+-------------+-------+--------------+
What I would like to do is basically loop through this result, running the following:
EXEC msdb.dbo.sp_send_dbmail
@recipients= 'email1', --email address from above query
@subject='Test email',
@body='You have X projects waiting' -- where X is the COUNT() term
for each of the rows.
My understanding is I could do this somewhat straightforward for each entry if I use a cursor, but, all the documentation and Stack Overflow results I've found strongly suggest this is not a good strategy.
What is the best way to do something like this?
Usually the reason cursors are discouraged is because there's ways to do what you want without using a cursor . Many developers start in procedural languages so loops are common and natural. Thinking in terms of set-based operations is not "natural" and so cursors are used to mimic loops.
In this case, using a cursor is appropriate because there's no set-based way to send individual emails.
Whether or not it's a good idea to send emails directly from you database server is another question...
Assuming this is going into some temp table or table var, you can add a row number to that result set, like so:
SELECT ROW_NUMBER() OVER (ORDER BY ProjectCodes.ProjectCode) RowNumber, ProjectCodes.ProjectCode, COUNT(Projects.ProjectsID), ProjectApprovers.EmailApprover
...
And then, using a while loop, iterate over that temp table and grab the values you require to execute the SP, matching by row number.
DECLARE @i int = 0
DECLARE @count int = -- length of query results
WHILE (@i < @count)
BEGIN
SELECT @emailAddress = EmailApprover, ...
FROM @YourTempResults
WHERE RowNumber = (@i + 1) -- row number is 1-based
EXEC msdb.dbo.sp_send_dbmail @recipients = @emailAddress, ...
SET @i = @i + 1
END
We're not doing any heavy lifting here though, so I wouldn't necessarily advice against a cursor in this case. Except that it's been so long, I'd have to refresh on how to code one. :)
You could define a function that did the send mail with the parameters you desire. Then do a select on your query where the select calls the function.
Select SendPMMail(ProjectCode, EmailAddress, ProjectCount) from
(SELECT ProjectCodes.ProjectCode as ProjectCode,
COUNT(Projects.ProjectsID) as ProjectCount,
ProjectApprovers.EmailApprover as EmailAddress
FROM Projects
INNER JOIN ProjectCodes
ON Projects.ProjectCodesID=ProjectCodes.ProjectCodesID
INNER JOIN ProjectApprovers
ON Projects.ProjectCodesID=ProjectApprovers.ProjectCodesID
WHERE ProjectApprovers.IsPrimaryApprover=1
GROUP BY ProjectCodes.ProjectCode, ProjectApprovers.EmailApprover)
You can do this:
Create a SQL AGENT JOB
: That will call your stored procedure every 2 time a week ( depending on your need)
You can control what to sent them or whom to send via stored proc.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.