SQL send db mail to multiple recipients with each related data - sql

I've created a two stored procedures, one holding the data info and the other is more for the call of db mail. I have a samples of the second stored procedure below as the issues is there.
BEGIN
SET NOCOUNT ON;
declare #Coord_ID varchar(20)
declare #Coord_Name varchar(25)
declare #Coord_Email varchar(75)
declare #CoordCursor as cursor
declare #tab char(1) = CHAR(9)
declare #emailBody varchar(100)
declare #sqlCommand varchar(1000) = 'sp_MZ_Get'
declare #qry varchar(1000)
set #CoordCursor = cursor Fast_Forward for
select distinct TARGET_ID, FULL_NAME, Email from vw_Coords where Email <> '' --and Target_ID = '7000001'
open #CoordCursor
fetch next from #CoordCursor into #Coord_ID,#Coord_Name, #Coord_Email
while ##FETCH_STATUS = 0
BEGIN
Print #Coord_ID + ' ' + #Coord_Email
set #emailBody = 'Member Renewal Transaction Activity for '+ #Coord_Name
DECLARE #RenewalActivity TABLE
(
Membership_Type varchar(25),
Member_ID varchar(20),
Chapter varchar(20),
Full_Name varchar(35),
Transaction_Date smalldatetime,
Renewal_Date smalldatetime,
AC_ID varchar(10),
AC_Name varchar(30)
)
insert into #RenewalActivity(Membership_Type, Member_ID, Chapter, Full_Name, Transaction_Date, Renewal_Date, AC_ID, AC_Name)
exec #sqlCommand #Coord_ID
if OBJECT_ID('tempdb..##temprenewals') is not null
drop table ##temprenewals
select * into ##temprenewals from #RenewalActivity
set #qry = 'select * from ##temprenewals'
EXEC msdb.dbo.sp_send_dbmail
#profile_name = 'Admin',
#recipients = #Coord_Email,
#query = #qry,
#execute_query_database = 'TOPS',
#subject = 'New Members and Renewals',
#body = #emailBody,
#attach_query_result_as_file = 1,
#query_attachment_filename='coord-s-9.csv',
#query_result_separator=#tab,
#query_result_no_padding=1
fetch next from #CoordCursor into #Coord_ID,#Coord_Name, #Coord_Email
END
close #CoordCursor
deallocate #CoordCursor
1st issue; the recipients receive the report contains all the data. as they should receive just what it related to them
example:
Member_ID | Chapter |Coord_Email
--------------------------------------
1 | A05 | Coord2#Email.com
5 | A01 | Coord1#Email.com
8 | A05 | Coord2#Email.com
12 | A01 | Coord1#Email.com
Currently 1,5,8 and 12 go to Coord1 and Coord2. the intention is 5 and 12 associated with A01 go to Coord1 and 1 and 8 go to Coord2.
2nd issue; the db mail is successfully queued as it stated in the log with 35 recipients. However, not all the recipients was included in the mail. Out of 90 recipients only 35 received the emails. i checked the 1st query and it resulted all the recipients "90".
Thank you in advance

Related

SQL Cursor and Email

I have a cursor in place that needs to send an email to one person containing all the rows associated with a certain field
To explain a bit further, i have a table which contains multiple rows, with one field containing the email address for all the rows associated with that email address.
I'm looking to send one email for that user with all the rows associated with that email address. At the moment, so if it has 4 rows, sends one email with all those rows. What its doing at the moment is sending 4 emails with all the rows associated with that email address
Essentially, just need it to send one email with all the rows for that email address
Thanks
Cursor loops through
Updates a table
Email then uses the variables to send the email
DECLARE #SUBJECT VARCHAR(100)
DECLARE #BODY VARCHAR(MAX)
DECLARE #EMAIL VARCHAR(60)
DECLARE #SUPERVISOREMAIL VARCHAR(60)
DECLARE #TABLEHTML VARCHAR(MAX)
DECLARE #TPROFILE VARCHAR(128)
DECLARE #ASSETREF VARCHAR(MAX)
DECLARE #PERSONREF VARCHAR(MAX)
DECLARE #USERNAME VARCHAR(MAX)
DECLARE #UPDATEDINVFIRE BIT
DECLARE #DATEUPDATEDINVFIRE DATETIME
DECLARE #DEVICEMODEL VARCHAR(MAX)
DECLARE #DESCRIPTION VARCHAR(MAX)
DECLARE CSR CURSOR
FOR SELECT ASSETREF, USERNAME, EMAIL, SUPERVISOREMAIL, UPDATEDINVFIRE, DATEUPDATEDINVFIRE FROM ##LEAVERUPDATE
OPEN CSR FETCH NEXT
FROM CSR INTO #ASSETREF, #USERNAME, #EMAIL, #SUPERVISOREMAIL, #UPDATEDINVFIRE, #DATEUPDATEDINVFIRE
WHILE ##FETCH_STATUS = 0
BEGIN
SET #SUBJECT = 'VFIRE DEVICE STATUS UPDATED FOR LEAVER'
SET #TABLEHTML = N'<P> The following user has had the following devices set to leaver status in vFire</P>' +
N'<P> Please be advised, these devices need to be returned immediately prior to the person leaving the business</P>' +
N'<table border="1">' +
N'<tr><th>CI Number</th><th>Username</th><th>Asset Model</th><th>Asset Description</th><th>Users Email Address</th><th>Supervisor EMail Address</th></tr>' +
CAST
((
SELECT
TD = ASSETREF, '',
TD = USERNAME, '',
TD = DEVICEMODEL, '',
TD = DESCRIPTION,'',
TD = EMAIL, '',
TD = SUPERVISOREMAIL,''
FROM ##LEAVERUPDATE
WHERE EMAIL = #EMAIL
FOR XML PATH('TR'), TYPE
) AS NVARCHAR(MAX) ) +
N'</TABLE>' +
N'<P> </P>';
EXEC msdb.dbo.sp_send_dbmail
#profile_name = #TPROFILE,
#recipients = #SUPERVISOREMAIL,
#copy_recipients='',
#blind_copy_recipients ='',
#subject = #SUBJECT,
#body = #TABLEHTML,
#body_format = 'HTML'
------------------------------------------
FETCH NEXT
FROM CSR INTO #ASSETREF, #USERNAME, #EMAIL, #SUPERVISOREMAIL, #UPDATEDINVFIRE, #DATEUPDATEDINVFIRE
END
CLOSE CSR
DEALLOCATE CSR

T-SQL - How to convert SELECT statements stored in table cells to a result?

I have a table that has 2 columns. The first is an ID and the second is a SQL SELECT statement related to that ID. What I need is some function or procedure that can parse every row and turn each SELECT statement into an output.
I am using MS SQL Server 2016
Example
Table Name: Test
|-----------|---------------------------------------------------------- |
| ID | SQL |
|-----------|-----------------------------------------------------------|
| 1 | SELECT COUNT(*) FROM dbo.Example WHERE SomeFilter = 'A' |
|-----------|-----------------------------------------------------------|
| 2 | SELECT COUNT(*) FROM dbo.Example WHERE SomeFilter = 'B' |
|-----------|-----------------------------------------------------------|
I can get a single result per line using code below but I am looking for a procedure that can process the whole table and output a result for every entry
DECLARE #SQL NVARCHAR(MAX)
SET #SQL = (SELECT [SQL] FROM [dbo].[Test])
EXECUTE sp_executesql #SQL
Desired output
|-----------|---------------------------------------------------------- |--------------|
| ID | SQL | Output |
|-----------|-----------------------------------------------------------|--------------|
| 1 | SELECT COUNT(*) FROM dbo.Example WHERE SomeFilter = 'A' | |
|-----------|-----------------------------------------------------------|--------------|
| 2 | SELECT COUNT(*) FROM dbo.Example WHERE SomeFilter = 'B' | |
|-----------|-----------------------------------------------------------|--------------|
Is something like this possible?
If yes - any assistance showing the steps would be appreciated. As mentioned I can get a line by line ad-hoc result per row but need an automated method to parse the whole table and return an extra column with results of each SQL query.
Thanks
You can use a simple looping mechanism as mentioned by Gordon.
DECLARE #ID INT = 1
DECLARE #MAXID INT = (SELECT MAX(ID) FROM dbo.Test)
DECLARE #SQL NVARCHAR(MAX)
CREATE TABLE #TMP (count_records INT, id_from_source INT)
WHILE #ID <= #MAXID
BEGIN
SELECT #SQL = (SELECT SQL FROM Test WHERE ID = #ID)
IF #SQL IS NOT NULL
BEGIN
INSERT #TMP (count_records)
EXECUTE sp_executesql #SQL
UPDATE #TMP SET id_from_source = #ID WHERE id_from_source IS NULL
END
SET #ID = #ID + 1
END
SELECT * FROM #TMP
Hope this is what you asked for
Create Procedure gen_SQL_STM
AS
DECLARE #stmList CURSOR;
DECLARE #id varchar(max);
DECLARE #sql varchar(max);
DECLARE #counts int;
BEGIN
SET #stmList = CURSOR FOR
SELECT stm.id, stm.sqlCol
from testTable stm
OPEN #stmList
FETCH NEXT FROM #stmList
INTO #id, #sql
WHILE ##FETCH_STATUS = 0
BEGIN
EXECUTE sp_executesql #sql= #counts OUTPUT
INSERT INTO testTable2(id, sqlstm, MYoutput_count)
SELECT #id, #sql, #counts
FETCH NEXT FROM #stmList
INTO #id, #sql
END;
CLOSE #stmList ;
DEALLOCATE #stmList;
END;
GO

Unable to develop body for email in SQL

I have written a stored procedure where "i have to compare values in two tables and send mail to the users which are not present in second table.
I have to automate this report .
But issue comes when i am trying to make mail body for the same.
The mail body is to be taken from table record ie column name REQ_Approval_EMAILBODY.Also the Recipient id has to be taken from table records ie cloumn name REQ_Approval_EMAILID.
This query has to execute for all the records one by one with respective email ID from table.
Please help me to sort out his.
Thanks in advance
CREATE PROCEDURE Email_Daily
AS
BEGIN
DECLARE #bodynew VARCHAR(Max)
DECLARE #query1 VARCHAR(Max)
DECLARE #Para VARCHAR(Max)
DECLARE #query2 VARCHAR(Max)
DECLARE #query3 VARCHAR(Max)
DECLARE #query5 VARCHAR(Max)
DECLARE #Yesterday VARCHAR(50)
SET #Yesterday = REPLACE(CONVERT(varchar(50),GETDATE()-1,102),'.','-')
DECLARE #TODAY_DDMMYYY VARCHAR(50)
SET #TODAY_DDMMYYY = REPLACE(CONVERT(varchar(50),GETDATE()-1,6),' ','-')
SELECT * into #Temp3_New_Table
FROM(
SELECT [MessageIdentifier]
,[MessageIdentifier_Archive]
,CONVERT(DATE,REQ_SentDate) AS REQ_SentDate
,[REQ_Token]
,[REQ_Approval_Number]
,[REQ_Order_Number]
,[REQ_Document_Number]
,[REQ_Approval_EMAILID]
,[REQ_Approval_EMAILBODY]
,[REQ_Approval_EMAIL_Subject]
,[RES_Date]
,[IsValid]
,[Response_MessageIdentifier]
,[ReSubmit_Count]
,'0' as Flag
FROM [SAEI].[dbo].[Approval_EMAIL_LOG]
where CONVERT(DATE,REQ_SentDate) = #Yesterday
and res_date is null
and req_approval_number+req_order_number+req_document_number not in
(SELECT
[RES_Approval_Number]+[RES_Order_Number]+[RES_Document_Number]
FROM [SAEI].[dbo].[Approval_Response_WEB_LOG]))as Tr
set #query5='select * from #Temp3_New_Table'
set #para='<p style="font-family:arial; font-size:14px">
Dear Team,
</br>
</br>
</br>
</p>'
Set #bodynew = #PARA
DECLARE #subjects VARCHAR(200)
DECLARE #FileAttachment VARCHAR(400)
DECLARE #Recipients VARCHAR(MAX)
DECLARE #copy VARCHAR(MAX)
set #Recipients='select [REQ_Approval_EMAILID] from #Temp3_New_Table'
drop table #Temp3_New_Table
End
try this
select #para = concat('<p style="font-family:arial; font-size:14px">Dear Team,</br></br>', [REQ_Approval_EMAILBODY],'</br></p>')
from #Temp3_New_Table
{where condition}
EDIT
if you want a cursor then you can try this
DECLARE evilCurse CURSOR FOR
SELECT [REQ_Approval_EMAILID]
,[REQ_Approval_EMAILBODY] = concat('<p style="font-family:arial; font-size:14px">Dear Team,</br></br>', [REQ_Approval_EMAILBODY],'</br></p>')
,[REQ_Approval_EMAIL_Subject]
FROM [SAEI].[dbo].[Approval_EMAIL_LOG]
where CONVERT(DATE,REQ_SentDate) = #Yesterday
and res_date is null
and req_approval_number+req_order_number+req_document_number not in
(SELECT [RES_Approval_Number]+[RES_Order_Number]+[RES_Document_Number]
FROM [SAEI].[dbo].[Approval_Response_WEB_LOG])
OPEN evilCurse
FETCH NEXT FROM evilCurse
INTO #Recipients, #bodynew, #subjects
WHILE ##FETCH_STATUS = 0
BEGIN
--do what ever you want to do to here
FETCH NEXT FROM evilCurse
INTO #Recipients, #bodynew, #subjects
END
CLOSE evilCurse;
DEALLOCATE evilCurse;

Using sp_send_dbmail with recieptent and content from single sql row

I have a table filled with oldUserID, newUserID, name and email. I want to use sp_send_dbmail to the email on each row. For example:
oldUserID | newUserID | name | email
21213125 | 2355233571 | Tom | tom#gmail.com
65465465 | 4564884664 | Mat | mat#gmail.com
And so on for 200 rows. Is there any way to send an sp_send_dbmail to the email on each row including oldUserID and newUserID? The output in the mail would be something like:
"Your old user id: 21213125, your new user id: 2355233571"
I would appreciate not to enter each emailadress manually.
Thank you!
DECLARE
#txt NVARCHAR(MAX)
, #name NVARCHAR(60)
, #email VARCHAR(100)
DECLARE cur CURSOR FAST_FORWARD READ_ONLY LOCAL FOR
SELECT 'Your old user id: ' + CAST(oldUserID AS NVARCHAR(100))
+ ', your new user id: ' + CAST(newUserID AS NVARCHAR(100)), name, email
FROM ...
OPEN cur
FETCH NEXT FROM cur INTO #txt, #name, #email
WHILE ##fetch_status = 0
BEGIN
EXEC msdb.dbo.sp_send_dbmail #profile_name = ...
, #recipients = #email
, #subject = #name
, #body = #txt
, #body_format = 'HTML'
FETCH NEXT FROM cur INTO #txt, #name, #email
END
CLOSE cur
DEALLOCATE cur

SQL Server email queue

I have an orders table which is populated with new orders frequently
Orders table:
OrderID OrderName EmailAddress Status
-----------------------------------------------------
1 iphone test#gmail.co.uk New
2 samsung nw#gmail.com New
3 nexus f#gmail.com Approved
For every order line which has status = 'New', I would like to set up a job to run every 30 minutes send an email to those recipients.
As per my understanding, you need to schedule a job which send an email notification if order status is 'New'.
If so create the following stored procedure
CREATE PROCEDURE NewOrders_Job
AS
BEGIN
DECLARE #OrderName varchar(200), #EmailAddress varchar(200)
SELECT
#OrderName = ' You have a sale for '+[OrderName]+', at +'CONVERT(VARCHAR(10),GETDATE(),)'+'
,#EmailAddress = [EmailAddress]
FROM [Orders table]
WHERE
[Status] = 'New'
IF(ISNULL(#EmailAddress,'')<>'')
BEGIN
--mail
DECLARE
#profile_name VARCHAR(200)
,#recipients VARCHAR(MAX)
,#copy_recipients VARCHAR(MAX)
,#blind_copy_recipients VARCHAR(MAX)
,#body VARCHAR(MAX)
,#body_format VARCHAR(MAX)
,#subject VARCHAR(MAX)
EXEC msdb.dbo.sp_send_dbmail
#profile_name = 'Your_Profile_Name'
,#recipients = #EmailAddress
,#copy_recipients = 'youremail#domain.com'
,#blind_copy_recipients = 'admin#yourdomain.com'
,#body = #OrderName
,#body_format = 'HTML'
,#subject = 'You have a new sales Order';
END
END
now, create a new job which run's for 30 mins with above stored procedure