How to concatenate string when setting a parameter in Transact-SQL - sql-server

First question here and is the following. I wrote the following code and everything works fine:
DECLARE #subject NVARCHAR(100)
SET #subject = 'Report executed on ' + CONVERT(VARCHAR(12), GETDATE(), 107)
SELECT #subject
Result: Report executed on Aug 17, 2012
but when trying to concatenate the previous string while setting the parameter of msdb.dbo.sp_send_dbmail procedure, it fails
EXEC msdb.dbo.sp_send_dbmail #profile_name='XXX',
#recipients='XXXX#XXXXX.com',
#subject = 'Report executed on ' + CONVERT(VARCHAR(12), GETDATE(), 107),
#body= #tableHTML,
#body_format = 'HTML';
I know I could declare and send a variable to the parameter but I would like to understand why it fails when concatenating directly in the parameter. thank you for your time and knowledge

Parameter values to T-SQL stored procedures cannot be expressions. They need to be either a constant or a variable.
From MSDN - Specify Parameters:
The parameter values supplied with a procedure call must be constants
or a variable; a function name cannot be used as a parameter value.
Variables can be user-defined or system variables such as ##spid.

You need to do:
DECLARE #Sub nvarchar(100);
SET #Sub = 'Report executed on ' + CONVERT(VARCHAR(12), GETDATE(), 107);
EXEC msdb.dbo.sp_send_dbmail #profile_name='XXX',
#recipients='XXXX#XXXXX.com',
#subject = #Sub,
#body= #tableHTML,
#body_format = 'HTML';

Related

Getting Empty Output

Iam trying to Execute Dynamic Query, But Iam getting Empty Output.Where I'm Wrong?
SET #SQL=N'
SELECT GETDATE(),'+#AMUID+','+ #BNO +
',LOT,BARCODEID,'+#ACTWT+',TARE_QUANTITY,''NA'',STAGE,0,0,0,
'+ #UNAME+ ','+#PR + ',GETDATE()
FROM DISPENSE_HOLD_START WHERE BATCH_NO='''+#BNO+''' AND BARCODEID='''+
#BARID +''' and IS_OUT=0';
PRINT(#SQL)
Here #AMUID,#BNO,#ACTWT etc are Input Parameters Declared with NVARCHAR(MAX) data type.They are dynamic Iam getting nothing When I Print this.
as you are not executing the query but printing it
this is same as
3+3=6 and "3"+"3"="33"
the dynamic queries are typically executed like this(simplest method)
DECLARE #IntVariable int;
DECLARE #SQLString nvarchar(500);
DECLARE #ParmDefinition nvarchar(500);
/* Build the SQL string one time.*/
SET #SQLString =
N'SELECT BusinessEntityID, NationalIDNumber, JobTitle, LoginID
FROM AdventureWorks2012.HumanResources.Employee
WHERE BusinessEntityID = #BusinessEntityID';
SET #ParmDefinition = N'#BusinessEntityID tinyint';
/* Execute the string with the first parameter value. */
SET #IntVariable = 197;
EXECUTE sp_executesql #SQLString, #ParmDefinition,
#BusinessEntityID = #IntVariable;
/* Execute the same string with the second parameter value. */
SET #IntVariable = 109;
EXECUTE sp_executesql #SQLString, #ParmDefinition,
#BusinessEntityID = #IntVariable;
Case#1 :
In your Above Query, You are using PRINT instead of EXEC. So Make sure you are executing the Query in your actual Code
EXEC(#SQL)
Case#2 :
If you are executing this, there is a possibility that if any of the Parameter Value is NULL, then the entire String will become NULL
If you add any Value to NULL the Result will be NULL
SELECT
'ABC',
'ABC'+NULL
Gives Me this
So Use ISNULL
SET #SQL = N'
SELECT
GETDATE(),
'+ISNULL(#AMUID,'')+','+ISNULL(#BNO,'')+',LOT,
BARCODEID,'+ISNULL(#ACTWT,'')+',TARE_QUANTITY,''NA'',STAGE,0,0,0,
'+ISNULL(#UNAME,'')+','+ISNULL(#PR,'')+',GETDATE()
FROM DISPENSE_HOLD_START
WHERE BATCH_NO='''+ISNULL(#BNO,'')+'''
AND BARCODEID='''+ISNULL(#BARID,'')+'''
and IS_OUT=0';
EXEC(#SQL);
Case#3
Looking at your Code, I think you don't need a Dynamic SQL here. Instead, you can directly go Like this
SELECT
GETDATE(),
#AMUID,
#BNO,
LOT,
BARCODEID,
#ACTWT,
TARE_QUANTITY,
'NA',
STAGE,
0,
0,
0,
#UNAME,
#PR,
GETDATE()
FROM DISPENSE_HOLD_START
WHERE BATCH_NO = #BNO
AND BARCODEID = #BARID
AND IS_OUT = 0
Works just fine for me
declare #val nvarchar(100) = 'tommy can you see me'
declare #SQL nvarchar(100) = N'SELECT GETDATE(), ''' + #val + '''';
PRINT(#SQL);

SQL query results to mail- Receiving Error formatting query, probably invalid parameters error

I am trying to send the invalid codes to mail. However when I execute the job for stored procedure, it completed fine and did not send any email. When I execute the query alone, I am getting the results. Did I miss any configuration setup?
CREATE PROCEDURE sp_Send_Email_Invalid_code
#MONTH AS int = 0
AS
BEGIN
DECLARE #Email_Subject AS nvarchar(250) = 'Codes Missing in master table';
DECLARE #Email_Receipients_To AS nvarchar(max) = 'xxx.yyy.com';
DECLARE #IsUseEmailConfig AS bit = 1;
DECLARE #Email_Category AS nvarchar(250);
SET #IsUseEmailConfig = 0
SET #Email_Category = 'Codes Missing in master table'
SELECT DISTINCT CODE
INTO #temp_1
FROM tblRegCode nolock
SELECT
*
FROM
#temp_1
DECLARE #Query nvarchar(max);
SET #Query = 'SELECT * FROM #temp_1';
EXEC msdb.dbo.sp_send_dbmail
#profile_name = 'psmEmailer',
#recipients = 'xxx.yyy.com',
#query = #Query,
#subject = 'Missing codes',
#attach_query_result_as_file = 1 ;
DROP TABLE #temp_1;
END
My SQL Server agent job is
DECLARE #MONTH AS int = 0
DECLARE #dt datetime = GETDATE()
SET #MONTH = DATEPART(mm, DATEADD(mm, -1, #dt))
EXEC sp_Send_Email_Invalid_code #MONTH
This is difficult to answer because there isn't anything obvious in the code above that is coursing the issue. Therefore the problem must be else where. My thoughts are 1) your query result set isn't returning anything. 2) Your email config is correct meaning the email can't be sent.
For number 1, we can't resolve this without checking your data, so moving on.
For number 2, try sending a simple email from the SQL instance using the send mail procedure in isolation. Like this:
EXEC msdb.dbo.sp_send_dbmail
#recipients = 'you#somewhere.com',
#subject = 'Send Mail Test',
#body = 'Testing',
#body_format = 'HTML';
Then is you don't receive an email check the failure logs in MSDB with the following query.
USE [msdb]
GO
SELECT
l.[description] AS 'Error failure',
f.[recipients],
f.[subject],
f.[sent_date],
f.[body],
f.[body_format]
FROM
[dbo].sysmail_faileditems f
JOIN [dbo].sysmail_event_log l
ON f.[mailitem_id] = l.[mailitem_id]
ORDER BY
f.[sent_date] DESC
If you do receive the test email I'd suggest the problem is with your query results that your trying to attach.
Just another thought. You may also need to use the param #execute_query_database and #query_attachment_filename.
Check https://msdn.microsoft.com/en-us/library/ms190307.aspx for details.
So, you can make from your SP just this:
CREATE PROCEDURE sp_Send_Email_Invalid_code
#MONTH AS int
AS
BEGIN
DECLARE #Query nvarchar(max) = 'SELECT [CODE ] FROM tblRegCode nolock';
EXEC msdb.dbo.sp_send_dbmail
#profile_name = 'psmEmailer',
#recipients = 'xxx.yyy.com',
#query = #Query,
#subject = 'Codes Missing in master table',
#attach_query_result_as_file = 1 ;
END
GO
In the SP you are not using #MONTH, why?
Try to add WITH EXECUTE AS OWNER in your SP, and run it via job.

Set dbo.sp_send_dbmail arguments to stored procedure return value?

I have stored procedure usp_emailRecipients that returns a semicolon-delimited list of email addresses. This is the list of email addresses that will receive an email sent using msdb.dbo.sp_send_dbmail.
How can I set the value of #recipients to the list returned in my stored procedure?
I cannot modify the stored procedure at the moment.
Something like:
EXEC msdb.dbo.sp_send_dbmail
#profile_name = 'Bob Jones',
#recipients = 'exec usp_emailRecipients',
#subject = 'Test email',
#execute_query_database = 'Sales',
#query = N'select * from sales',
#attach_query_result_as_file = 1,
#query_attachment_filename = 'Sales.txt'
Thanks.
The way you have this coded it will send a string literal as the value for recipients. This is not how this works. The way to do this is to use an OUTPUT variable in usp_emailRecipients. This will require a change in your procedure so you are using an OUTPUT parameter. Then you populate the variable like this.
declare #recipientList varchar(max)
exec usp_emailRecipients #recipientList OUTPUT
You would do this prior to calling sp_send_dbmail.
EXEC msdb.dbo.sp_send_dbmail
#profile_name = 'Bob Jones',
#recipients = #recipientList,
#subject = 'Test email',
#execute_query_database = 'Sales',
#query = N'select * from sales',
#attach_query_result_as_file = 1,
#query_attachment_filename = 'Sales.txt'
--EDIT--
Since you say you can not modify your stored procedure you are going to have to do something like use FOR XML to create a delimited list from the result set of your procedure.
This code is 100% untested because we have nothing to work with but it should be pretty close.
create table #EmailList
(
EmailAddress varchar(255)
)
insert #EmailList
exec usp_emailRecipients
declare #recipientList varchar(max)
select #recipientList = STUFF((select ';' + EmailAddress
from #EmailList
FOR XML PATH('')), 1, 1, '')
Then you can send the email like I posted above.
Do you have the flexibility to turn the usp_emailRecipients procedure into a scalar function, lets say udf_emailRecipients? If so, you can then do the following:
Declare #recipients as varchar(max)
Select #recipients= udf_emailRecipients();
EXEC msdb.dbo.sp_send_dbmail
#profile_name = 'Bob Jones',
#recipients,
#subject = 'Test email',
#execute_query_database = 'Sales',
#query = N'select * from sales',
#attach_query_result_as_file = 1,
#query_attachment_filename = 'Sales.txt'

SQL Server msdb.dbo.sp_send_dbmail

I want to publish some query results in the e-mail in a structured format. I'm using the #body_format as 'HTML'.
I want to do like:
Declare #processed_rows int
declare #Sourcetype varchar(100)
select #sourcetype = (some SQL query)
select #processed_rows = (some SQL query)
exec msdb.dbo.sp_send_dbmail
#body='some HTML' ,
#subject = 'IGD-DEVELOPMENT SERVER UPDATED',
#profile_name = 'IGDMail',
#recipients = ' abhisheks#exzeo.com
When I'm executing msdb.dbo.sp_send_dbmail, I want to pass these variables in the #body argument of stored procedure and use them in the final email, please help to achieve this?
You'll need to declare another variable to hold your HTML code:
DECLARE #HTML NVARCHAR(MAX)
SET #HTML = 'SOME HTML HERE' + CAST(PROCESSED_ROWS AS VARCHAR) + 'SOME MORE HTML' + #SOURCETYPE
EXEC MSDB.DBO.SP_SEND_DBMAIL
#BODY = #HTML
, #BODY_FORMAT = 'HTML'
ETC.....
You get the idea...

Calling stored procedure with OUTPUT parameter in dynamic SQL

I am calling a stored procedure with OUTPUT parameter using dynamic SQL.
set #cSql='EXEC '+#cName+'.dbo.uspNDateGet '''
+convert(varchar(10),#dtAsOn,102)+''','''
+#cBr+''','''
+#cLCode+''','''
+convert(varchar(10),#dtNDate,102)+''' OUTPUT'
exec(#cSql)
On executing the script, I get following error.
Cannot use the OUTPUT option when passing a constant to a stored procedure.
Without using dynamic SQL, the script gives me the required result.
EXEC uspNDateGet #dtAsOn,#cBr,#cLCode,#dtNDate OUTPUT
You need to pass parameters from outside into the inside query.
Here I show you the generic case:
declare #sql nvarchar(max);
declare #Out1 nvarchar(10);
declare #Out2 nvarchar(10);
declare #ParmDef nvarchar(max);
set #ParmDef =
' #Parm_Out1 nvarchar(10) '
+ ', #Parm_Out2 nvarchar(10) ' ;
set #sql='EXEC myproc #Parm_Out1 OUTPUT, #Parm_Out2 OUTPUT '
exec sp_executesql #sql, #ParmDef, #Parm_Out1 = #Out1, #Parm_Out2 = #Out2
In this particular instance, you don't actually need dynamic SQL at all.
You can parameterize the name of the stored procedure being called with EXEC, and pass the parameters normally. This is documented here:
DECLARE #dtNDate datetime, #procName nvarchar(386);
SET #ProcName = #cName + N'.dbo.uspNDateGet';
EXEC #procName
#dtAsOn = #dtAsOn,
#cBr = #cBr,
#cLCode = #cLCode,
#dtNDate = #dtNDate OUTPUT

Resources