SQL Server DB_mail sending multiple counts - sql

I am using db_mail in SQL Server 2008 r 2 to send counts of mail daily.
How can I send 1 email daily that has 3 counts ( Count A, Count B, Count C) included?

You can use a query with multiple columns as you want.
[ #query = ] 'query'
Is a query to execute. The results of the query can be attached as a file, or included in the body of the e-mail message. The query is of type nvarchar(max), and can contain any valid Transact-SQL statements. Note that the query is executed in a separate session, so local variables in the script calling sp_send_dbmail are not available to the query.
Sample query:
EXEC msdb.dbo.sp_send_dbmail
#profile_name = 'Adventure Works Administrator',
#recipients = 'danw#Adventure-Works.com',
#query = 'SELECT COUNT(*) As CountA, 1 As CountB, 2 As CountC
FROM AdventureWorks2012.Production.WorkOrder
WHERE DueDate > ''2004-04-30''
AND DATEDIFF(dd, ''2004-04-30'', DueDate) < 2' ,
#subject = 'Work Order Count',
#attach_query_result_as_file = 1 ;
You can also use a variable to set in the body.

Related

SQL Mail to send emails to users specified in a query only

I've about 1 month of experience when it comes to SQL and I wanted to send emails to customers based on query criteria. The challange I have is that the emails should only go to users emails that show up in the query. Below is an example of the data. I have no idea what I should do to setup the auto emailing based on a query. Any help is greatly appreciated!
My query would look like this,
select *
from [Tbl]
where [Date Certificate is Expiring]
Between getdate()-372 AND getdate()-371
OUTPUT:
USER ID | Email | Date Certificate is Expiring
NOTE: I do not have access to Visual Basic, SSRS, SSIS, or any other tool than Database Engine and dbMail
Please create DB mail profile first, then put it into below query:
DECLARE #MailRecipients NVARCHAR(MAX);
SELECT #MailRecipients = STUFF((
SELECT DISTINCT ';' + t.Email
FROM [Tbl] t
WHERE t.[Date Certificate is Expiring] BETWEEN GETDATE()-372 AND GETDATE()-371
FOR XML PATH(''),TYPE).value('(./text())[1]','VARCHAR(MAX)'),1,1,'')
;
IF COALESCE(#MailRecipients,'') <> ''
BEGIN
EXEC msdb.dbo.sp_send_dbmail
#profile_name = ..., -- <-- you have to create DBMailProfile first
#recipients = #MailRecipients,
#subject = 'Email about expiring stuff',
#body_format = 'HTML',
#body = 'Hi there, your something is expired',
#importance = 'Normal'
END

Must pass parameter number 4 and subsequent parameter as '#name =value'

I've got the following stored procedure that runs perfectly in SSMS.
Create Store Proc MyTT
SELECT
MAX(TableName) as TableName,
aco_code,acc_code,
ctr_id,cte_id,usr_code,
-- convert(datetime,convert(varchar,current_timestamp,112),112)
Cast(DATEPART(hour,current_timestamp) as varchar(3))+':'+ CAST(DATEPART(minute,current_timestamp) as varchar(3))as [Time]
INTO #AB
FROM
(
SELECT 'TM_ACO_Account_Comment'as TableName,
a.aco_code,
a.acc_code,
a.ctr_id,
a.cte_id,
a.usr_code
FROM
TM_ACO_Account_Comment a with(NOLOCK)
UNION ALL
SELECT 'TM_ACO_Account_Comment'as TableName,
b.aco_code,
b.acc_code,
b.ctr_id,
b.cte_id,
b.usr_code
FROM
[172.17.14.77].[IS_ND_BLAKE].[dbo].[TM_ACO_Account_Comment] b with(NOLOCK)
)zzz
GROUP BY aco_code,
acc_code,
ctr_id,
cte_id,
usr_code
HAVING COUNT(*) = 1
ORDER BY
aco_code
SELECT *
FROM
#AB
DROP TABLE #AB
But when I try to include the procedure in a query to send out mail, I get the following error:
Must pass parameter number 4
My Mail Query looks like this.
EXEC msdb.dbo.sp_send_dbmail
#profile_name = 'DBMail',
#recipients = 'mitch#domain.com',
#query = 'exec SP,`MYTT`
#execute_query_database = 'MYDB',
#subject = 'Work Order Count',
#attach_query_result_as_file = 1 ;
In your EXEC msdb.dbo.sp_send_dbmail command, you seem to have not closed the string literal in this line properly:
#query = 'exec SP,`MYTT`
It is missing a closing ', as well as a comma to separate this argument from the next one:
#query = 'exec SP,`MYTT`',
However, the passed query itself looks a bit strange. Your stored procedure is called MyTT and if you meant it to be called in the query you are passing to msdb.dbo.sp_send_dbmail, you specified the exec statement incorrectly. It should probably be simply like this:
#query = 'exec MyTT',
Although it might be a good idea to specify the database and the schema too:
#query = 'exec YourDBName.YourSchema.MyTT',
I have slightly corrected the name proper to match the one in your definition exactly. If your server's default collation is case-insensitive (which is likely), that may be unnecessary, but it would not harm to be consistent in such matters.

sp_send_dbmail sending mail even if condition is false - SQL

I have an IF statement part of a stored procedure as follows :
BEGIN TRY
IF EXISTS (SELECT which I have confirmed returns no results, has a variable called from another table in the where clause)
BEGIN
EXEC msdb.dbo.sp_send_dbmail
#profile_name = #dynamic_profile,
#recipients = #dynamic_recipient,
#subject = #subjectline,
#body = #mailHTML,
#body_format = 'HTML';
END
END TRY
This is tied to a job that runs every 15mins.
Why is it keep sending me blank emails when the IF statement asks to skip the mail sending if the select returns no results?
My NOCOUNT is set to ON
Try - instead:
IF (SELECT COUNT(*) FROM whatever) > 0
BEGIN
--MAIL
END

SQL Server stored procedure if statement injection string

Using SQL Server I am trying to inject a string into a SQL statement based on an if statement, note that am trying to accomplish this inside a stored procedure.
I am currently getting an error for this code:
Declare #topString varchar(240)
IF #topRecords > 0
SET #topString = 'top 500'
ELSE
SET #topString = ''
SELECT #topString * FROM( //incorrect syntax near FROM
SELECT top 500 c.Id as [Customer Id],....
UNION
SELECT top 500 c.Id as [Customer Id],....
)as table1
Order by 1 desc
Edit
if somethingTrue
#whereCondition = '1 = 1 '
else
#whereCondition = branch = #branch
select * from table
where #whereCondition AND etc...
Correct
for injection inside an if statement go with Jodrell
but if you need a dynamic top then go with what was suggested by Kaf.
thanks both for the help!
If you want to decide number of top records depending on #topRecords, you can do it using an INT or BIGINT depending on the number of records needed.
DECLARE #top INT --This is declared as an int here
IF #topRecords > 0
SET #top = 500
ELSE
SET #top = 5000000 --Make it more than records if you need all
--or make it 0 if no records needed.
--#top has to be >=0
--How to use it
SELECT TOP (#top) * FROM YourTable
EDIT: Your question had only a top injection initially. However, If you need more injections (as per your recent question edit) then I would suggest to use a dynamic query as per #Jordell's answer.
You can't inject statement parts as variables like that, however you can change most values for parameters.
Having a stored procedure perform operations that may require different query plans, based on a parameter is a bad idea, the results of this SP could vary wildly based on the value of the #topRecords parameter. You would need to use the RECOMPILE option to warn the query engine, mitigating much of the benefit of SPs. Have you considered just having two stored procedures?
If you want to do it dynamically, you could build the whole statement dynamically, making one big string, then execute that.
You should investigate using sp_executesql to execute the string/VarChar. Then similar queries will benefit from query plan reuse.
As ever Sommarskog is a good reference.
Something like this
DECLARE #topString varchar(240);
DECLARE #statement varchar(max);
IF #topRecords > 0
SET #topString = 'TOP 500';
ELSE
SET #topString = '';
SET #statement = 'SELECT ' + #topString + ' * FROM
(
SELECT TOP 500 c.Id as [Customer Id], ....
UNION
SELECT TOP 500 c.Id as [Customer Id], ....
) table1
ORDER BY 1 DESC'
/* Then execute #statement */
EXEC sp_executesql #statement

SQL mail ------DATABASE MAIL

Dear all,
I am using SQL Server 2008.
I am facing a scenario where I have to send mail to single or multiple user depending on the query. I tried this stmt to send mail to multiple recipients
EXEC msdb.dbo.sp_send_dbmail
#profile_name = 'imran' ,
#recipients= 'imran.khan#bbraun.com;amol.puranik#bbraun.com',
#subject = 'Test mail'
It succesfully sent mail.
Now I want to send mail depending on query. With single employee it is no issue, but if it is more then one employee how can I mail to multiple recipients.
That is my question is in this sp to send multiple recipients one has to separate addresses with ; . How can I arrange recipients so that the ; comes in between.
Thank you.
Unfortunately, you're not giving us a lot to go on - you don't show us the query to select your employees, you're not telling us anything about what the Employee table looks like, so all we can do is guessing - at best.
So here's my guess: you want to somehow select multiple employees, and their e-mail addresses should be concatenated together, separated by a semicolon (;), and then used for your sp_send_dbmail call.
One method to do this could be this:
DECLARE #recipients VARCHAR(4000)
SELECT
#recipients = STUFF((SELECT ';' + EMail
FROM dbo.Employees
WHERE (some condition here to find the right employees)
FOR XML PATH('')
), 1, 1, '')
EXEC msdb.dbo.sp_send_dbmail
#profile_name = 'imran',
#recipients,
#subject = 'Test mail'
Use a function like this -
CREATE FUNCTION coltocsv
(
--your input parameters
)
RETURNS nvarchar(3000)
AS
BEGIN
-- Declare the return variable here
declare #keywords nvarchar(3000)
--Build your csv string of keywords
Select #keywords = null
SELECT #Keywords = Coalesce(#Keywords + '; ', '') +
ColumnName
from Table
where <some condition>
--- Return the result of the function
RETURN #keywords
END
for the recipients, you can seggregate the miultiple email id's by [];
declare #ccmailid varchar(2000);
select #ccmailid = stuff((select '],['+ mailid from table_name
order by '],['+ mailid
for xml path('')),1,2,'')+']'
EXEC msdb.dbo.sp_send_dbmail
#profile_name = 'imran' ,
#recipients= #ccmailid,
#subject = 'Test mail'