I am using msdb.dbo.sp_send_dbmail to send email based upon query results. It works fine until I used and isnull in my query. The query returns the right results but a message is not triggered. When the field in question is not null it works fine.
I want to validate builddate against checkdate. When they do not match I want to send an email. I used isnull for cases when the table did not populate and builddate is null.
My base query is as follows:
SELECT
ISNULL(MAX(convert(date,Builddate)),DATEADD(YEAR,-10,GETDATE())) AS
[builddate],
CONVERT(VARCHAR(10),GETDATE(),121)AS [checkdate]
FROM dbo. XXXX_BPCCustomer_Test
HAVING ISNULL(MAX(convert(date,Builddate)),DATEADD(YEAR,-10,GETDATE()))
<>CONVERT(VARCHAR(10),GETDATE(),121)
the results are builddate=2010-01-03 and checkdate = 2020-01-3
the code that pushes the email is as follows:
DECLARE #recordcount INT
SELECT #recordcount = ISNULL(COUNT(*),0)
FROM [YCH-REPORTING\YCHANALYTICS].[x3v7].[dbo].[Dataset_BPCCustomer_Test]
HAVING ISNULL(MAX(convert(date,Builddate)),DATEADD(YEAR,-10,GETDATE()))
<>CONVERT(VARCHAR(10),GETDATE(),121)
IF (#recordcount > 0)
BEGIN
EXEC msdb.dbo.sp_send_dbmail
#profile_name = 'SQL Mail',
#recipients = 'john.XXXXXXXXX.com;XXXXXXXXXXXXXXX',
#query = 'SELECT
ISNULL(MAX(convert(date,Builddate)),DATEADD(YEAR,-10,GETDATE())) AS
[builddate],
CONVERT(VARCHAR(10),GETDATE(),121)AS
[checkdate],"Dataset_BPCCustomer_Test" as [Table]
FROM [XXXXXX\YCHANALYTICS].[x3XX].[dbo].
[Dataset_BPCCustomer_Test]
HAVING
ISNULL(MAX(convert(date,Builddate)),DATEADD(YEAR,-10,GETDATE()))
<>CONVERT(VARCHAR(10),GETDATE(),121)'
,
#subject = ' DataSet did not update or isnull',
--#attach_query_result_as_file = 1,
--#query_result_header = 0,
#body =0;
END
It appears that it is not processing the isnull statement? Any suggestions and thanks in advance.
It looks like there are double-quotes ("Dataset_BPCCustomer_Test") inside #query, making the statement incorrect.
Those should each be two single quotes (apostrophes):
#query = 'SELECT
ISNULL(MAX(convert(date,Builddate)),DATEADD(YEAR,-10,GETDATE())) AS
[builddate],
CONVERT(VARCHAR(10),GETDATE(),121)AS
[checkdate],''Dataset_BPCCustomer_Test'' as [Table]
FROM [XXXXXX\YCHANALYTICS].[x3XX].[dbo].
[Dataset_BPCCustomer_Test]
HAVING
ISNULL(MAX(convert(date,Builddate)),DATEADD(YEAR,-10,GETDATE()))
<>CONVERT(VARCHAR(10),GETDATE(),121)'
Related
I have a SQL Server stored procedure, which runs via a scheduled task every 7 minutes, and which is used to send an email to the recipients concerned, once the condition of the number of records returned by request is greater than or equal to 1.
the procedure code is:
Begin
declare #recordCount int
declare #bodytext varchar(200)
select #recordCount = isnull(count(*), 0)
from table where .............
IF (#recordCount > 0)
set #bodytext = N'Message'
EXEC msdb.dbo.sp_send_dbmail
#profile_name = 'Profile',
#recipients = 'Test#test.com',
#subject = 'Title',
#Body = #bodytext,
#query = N'Select Column1,Column2
from Table
inner join Table2 on .........
where ........................',
#execute_query_database = N'DB'
End
End;
My problem is that I'd like to send the email, only once, since the scheduled task runs every 7 minutes, but i can't find the track how i can achieve that without adding new columns in the "Table".
I have a code to send Birthday Emails to Customers, the query works fine, but the SQL Mail server always send a Birthday Email to all Customers, even he has no Birthday
use Insurance
go
select
Customer.CustomerID
,Customer.FirstName
,Customer.LastName
,Customer.Birthday
,Customer.Email
from Customer
where Customer.CustomerID = Customer.CustomerID and
DAY([Birthday]) = DAY(GETDATE())
AND MONTH([Birthday]) = MONTH(GETDATE())
declare #Receipientlist nvarchar(4000)
set #Receipientlist =
STUFF((select ';' + Email FROM dbo.Customer FOR XML PATH('')),1,1,'')
EXEC msdb.dbo.sp_send_dbmail #profile_name='test',
#recipients=#Receipientlist,
#subject='Insurance',
#body='Happy Birthday.
Today is your Birthday.'
Your query at the top of your batch has nothing to do with your statement that executes msdb.dbo.sp_send_dbmail. If you only want to email customer's who's birthday it is, you need to filter in the statement that creates the recipients (and you don't need the previous statement):
DECLARE #RecipientList nvarchar(4000);
--I removed the CustomerID = CustomerID clause, as it'll always equal itself,
--apart from when it's value is NULL (and I doubt it'll ever be NULL)
SET #RecipientList = STUFF((SELECT N';' + Email
FROM dbo.Customer
WHERE DAY([Birthday]) = DAY(GETDATE())
AND MONTH([Birthday]) = MONTH(GETDATE())
FOR XML PATH(N''),TYPE).value('.','nvarchar(4000)'), 1, 1,N'');
EXEC msdb.dbo.sp_send_dbmail #profile_name = 'test',
#recipients = #RecipientList,
#subject = 'Insurance',
#body = 'Happy Birthday.
Today is your Birthday.';
I've also changed the way that the value from the subquery is returned, used TYPE and the value clauses. Email addresses can contain some special characters, and these would have been escaped without the usage of TYPE (for example & would become &). (I've also corrected the spelling of #RecipientList.)
first of all, sorry for my English,
I am a newbie in stored procedure, so i'm seek for a help on it.
I have a project that need me to create a SP for a configurable table name and column name. I've manage to pass the table name and column name value from vb/vb.net and now i'm stuck on SP, below are sample of my code.
example :
frmTblname = table_a
frmClmnName = clm_A1, clm_A2, clm_A3, clm_A4, clm_A5,
toTblName = table_b,
toClmnName = clmn_b1,clmn_b2, clmn_b3, clmn_b4, clmn_b5
from vb/vb.net Rslt = ConnectionExec.RunSP(con, "sp_configurable_insert", frmTblname, frmClmnName, toTblName, toClmnName)
how to add that into SQL insert query?
Here are my SP
CREATE procedure [dbo].[sp_configurable_insert] #fromTable nvarchar(50),#fromColumn nvarchar(4000),#toTable nvarchar(50),#toColumn nvarchar(4000)
I've tried this but it seems not giving any result.
set #Query1 = 'insert into '+#toTable+'('+quotename(#toColumn)+')
select top 20 '+#fromColumn+'
from '+#fromTable+'
can anyone help me, please?
Thanks :)
Things to change:
quotename(#toColumn) will return '[clmn_b1,clmn_b2, clmn_b3, clmn_b4, clmn_b5]' which is not correct. Remove quotename() or set #toColumn = '[clmn_b1], [clmn_b2], [clmn_b3], [clmn_b4], [clmn_b5]'.
your query statement is unfinished.
Stored procedure (with correct syntax):
CREATE procedure [dbo].[sp_configurable_insert]
#fromTable nvarchar(50),
#fromColumn nvarchar(4000),
#toTable nvarchar(50),
#toColumn nvarchar(4000)
AS
BEGIN
DECLARE
#stm nvarchar(max),
#err int
SET #stm =
N'insert into '+#toTable+' ('+#toColumn+') select top 20 '+#fromColumn+' from '+#fromTable
EXEC #err = sp_executesql #stm
IF #err <> 0 BEGIN
RETURN #err
END
RETURN 0
END
you need to add EXECUTE(#Query1) to your SP and it will work
Add at the end of your query:
exec sp_executesql #Query1
So it should look like:
set #Query1 = 'insert into '+#toTable+'('+quotename(#toColumn)+')
select top 20 '+#fromColumn+'
from '+#fromTable+'
exec sp_executesql #Query1
So pay attention that #Query1 is incomplete or contains error coz quotes is unbalanced.
I am trying to write dynamic SQL that can accept up to 50 parameters. It can be 1 or 10 or 15. The limit is 50 from the main sproc but the input to the dynamic sql is not defined.
I have created this dynamic statement through a while loop. It will read the number of parameter in a table(3 in this example) and generates the statement below. I am not concerned with the performance of the while loop because the tables/input are very small:
--generated from while loop
DECLARE #rParam1 NVARCHAR(MAX)
DECLARE #rParam2 NVARCHAR(MAX)
DECLARE #rParam3 NVARCHAR(MAX)
SELECT #rParam1= Parameter_Name FROM [Template_Params] WHERE Key=12345 AND Sort_Order=1
SELECT #rParam2= Parameter_Name FROM [Template_Params] WHERE Key=12345 AND Sort_Order=2
SELECT #rParam3= Parameter_Name FROM [Template_Params] WHERE Key=12345 AND Sort_Order=3
DECLARE #BODY NVARCHAR(MAX);
SELECT #BODY = Body FROM [Template] WHERE Key=12345
SET #Body = REPLACE(#Body,#rparam1,#PARAM_Input1)
SET #Body = REPLACE(#Body,#rparam2,#PARAM_Input2)
SET #Body = REPLACE(#Body,#rparam3,#PARAM_Input3)
SELECT #BODY
This so far works good.
The stored procedure can have 50 inputs but for example I will limit to 5 (only used 3)
--this is from the main sproc
DECLARE #PARAM_Input1 NVARCHAR(MAX)='test',
#PARAM_Input2 NVARCHAR(MAX)='test1',
#PARAM_Input3 NVARCHAR(MAX)='test2',
#PARAM_Input4 NVARCHAR(MAX),
#PARAM_Input5 NVARCHAR(MAX),
#param_input6 nvarchar(max)
Now I need to get these values into the dynamic SQL so my final Dynamic statement should have
SET #Body = REPLACE(#Body,#rparam1,'test')
SET #Body = REPLACE(#Body,#rparam2,'test1')
SET #Body = REPLACE(#Body,#rparam3,'test2')
This is where I am stuck, I do not want to write the REPLACE Statement 50 times like this.
SET #SQL=REPLACE(#SQL,'#PARAM_Input1',''''+#PARAM_Input1+'''')
I tried a cursor but the name of the variable has to be dynamic and it's not in the same scope so the values from the sproc are not being passed.
It might not be possible in SQL to do what you have in mind. A solution could be if you can send a table as parameter to contain the information as below (or generate it dinamically:
ParameterName | Value
<value of #rParam1> | <value of #Param_Input1>
<value of #rParam2> | <value of #PARAM_Input2>
Then, update #BODY variable
SELECT #BODY = Body FROM [Template] WHERE Key=12345
UPDATE <TableParameter_Or_Variable>
SET #Body = REPLACE(#Body, ParameterName, Value)
I don't know how you obtain the values for #PARAM_InputX, but for `#rParamX' you can do something like:
INSERT INTO #Table
SELECT Parameter_Name AS ParameterName, null AS Value
[Template_Params] WHERE Key=12345
ORDER BY sort_order
and then update the rows accordingly. On #Table you can open a cursor and match the current row to #PARAM_InputX.
I use the #query perimeter in sp_send_dbmail to send out an e-mail with a list of warnings (the warnings are returned by the #query perimeter). The #query perimeter is listed as text in the e-mail. All of the records returned from the #query perimeter and displayed in the e-mail has a line break between them. ie. If I have 4 records, I would have 8 lines because of line breaks.
How do I turn the line breaks off? I read the the msdn article for sp_send_dbmail, but it didn't mention any attributes that could be changed that would affect the line breaks.
Code:
BEGIN
EXEC MSDB.DBO.sp_send_dbmail
#PROFILE_NAME = 'Alerts',
#RECIPIENTS = #MAIL,
#SUBJECT = #NEWSUBJECT,
#BODY = #NEWBODY,
#QUERY =
'SET NOCOUNT ON
DECLARE #HEXSTRING AS VARCHAR(100)
SET #HEXSTRING = (SELECT HEXADECIMAL_STRING FROM mydb.dbo.statusupdates
WHERE MACHINE_ID = ''1111'' AND DATEDIFF(MI, TIME_DATE_RECEIVED, GETDATE()) <= 60)
SELECT [Warning_Description] FROM mydb.DBO.BINARYTOTABLE(mydb.DBO.HEXTOBINARY(#HEXSTRING)) AS ABB1
JOIN mydb.DBO.WarningMessages ON mydb.DBO.WarningMessages.[Bit_Offset] = ABB1.BITPLACE
WHERE BITVALUE = 1 AND ALERT_LEVEL = ''WARNING''',
#QUERY_RESULT_HEADER = 0,
#ATTACH_QUERY_RESULT_AS_FILE = 0;
END
Old post, but probably worth checking #query_result_width parameter of sp_send_dbmail
See http://technet.microsoft.com/en-us/library/ms190307(v=sql.110).aspx
If the data width in a column exceeds #query_result_width (default of 256) a new line will be added.
Steve
I have always used CHAR(13)+CHAR(10) to create line breaks in tsql. You will have to replace it by ' '.
I ended up putting everything into the #BODY parameter of SP_SEND_DBMAIL. Query results from a SELECT statement could be concatenated with regular text into a string and you can use HTML to format the resulting text.
try this and see what you get ...
#query = REPLACE(#query,CHR(13),'')