I'm creating a task to send an email with a SQL output as a csv file attached in the SQL Server Agent. Normally not a problem, my code looks like this:
declare #tab char(1) = char(9)
EXEC msdb.dbo.sp_send_dbmail
#profile_name = 'MailProfile',
#recipients = 'email#email.com',
#subject = 'TheSubject',
#body = 'TheBody',
#query = 'select * from ##TempTableBeingUsed',
#Attach_Query_result_as_file = 1,
#query_attachment_filename = 'report.csv',
#query_result_separator = #tab,
#query_result_no_padding=1,
#exclude_query_output=0,
#append_query_error =0,
#query_result_header=1
And this normally works, but with the current query the column names are line wrapping, and a lot of the data rows are line wrapping, without a line break being present. It looks like it does this whenever the length of the row is more then 255 characters. Is there any way to bypass this? Looks it may be the same as this issue, SQL Email to CSV, Results have Line Splitting issues.
Adding the option:
#query_result_width=500
fixed it
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 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)'
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.)
I have the following table:
CREATE TABLE [dbo].[MyTable](
[Day_ID] [nvarchar](50) NULL,
[SAS] [nvarchar](50) NULL,
[STAMP] [datetime] NULL DEFAULT (getdate())
)
which contains this data:
'2017_12_06_01','Red'
'2017_12_06_02','Yellow'
'2017_12_06_03','Green'
'2017_12_06_04','Blue'
I also have a SP which read all the data from MyTable and send it in the body of an e-mail message.
SET NOCOUNT ON;
EXEC msdb.dbo.sp_send_dbmail
#profile_name = 'MyMailProfile'
,#recipients = 'me#account.com'
,#subject = 'This is the object'
,#body = 'This is the body:'
,#body_format = 'TEXT'
,#query = 'SET NOCOUNT ON select [Day_ID],[SAS] from MyTable SET NOCOUNT OFF'
,#attach_query_result_as_file = 0
,#query_result_separator = '|'
,#exclude_query_output = 1
,#query_result_no_padding = 0
,#query_result_header = 0
,#append_query_error=1
Everything works but my problem is that in the body the results appear like these:
2017_12_06_01 |Red
2017_12_06_02 |Yellow
2017_12_06_03 |Green
2017_12_06_04 |Blue
In other words SQL Server know that the columns could be 50 characters long so they fill the space that doesn't contain characters with spaces. This is very boring if you consider that happen also if you write numeric values into a column, for example, NUMERIC.
I've tried with LTRIM and RTRIM but nothing changed.
I am using SQL Server 2005.
The parameter #query_result_no_padding should allow you to do this.
Change it from:
#query_result_no_padding = 0
to
#query_result_no_padding = 1
[ #query_result_no_padding ] #query_result_no_padding The type is bit.
The default is 0. When you set to 1, the query results are not padded,
possibly reducing the file size.If you set #query_result_no_padding to
1 and you set the #query_result_width parameter, the
#query_result_no_padding parameter overwrites the #query_result_width
parameter. + In this case no error occurs. If you set the
#query_result_no_padding to 1 and you set the #query_no_truncate
parameter, an error is raised.
Source: https://learn.microsoft.com/en-us/sql/relational-databases/system-stored-procedures/sp-send-dbmail-transact-sql
You need to run two queries - first to compute the actual lengths, the second to retrieve the data for the email. Obviously, this can have a high cost.
Something like:
declare #maxDay int
declare #maxSAS int
select #maxDay = MAX(LEN(RTRIM(Day_ID))),#maxSAS = MAX(LEN(RTRIM(SAS))) from MyTable
declare #sql varchar(max)
set #sql = 'SET NOCOUNT ON select CONVERT(nvarchar(' + CONVERT(varchar(10),#maxDay) +
'),[Day_ID]) as Day_ID,CONVERT(nvarchar(' + CONVERT(varchar(10),#maxSAS) +
'),[SAS]) as SAS from MyTable SET NOCOUNT OFF'
And then use #sql in you sp_send_dbmail call.
I've tried with LTRIM and RTRIM but nothing changed.
It wouldn't. Each column in a result set has a single fixed type. The input to your e.g. RTRIM() calls is an nvarchar(50). Without knowing the contents of all rows, what possible data type can SQL Server derive for the output from that RTRIM() using expression? It can only still be nvarchar(50) and so that's still the type of the column in the result set. For all the server nows, there could be a row containing 50 non-whitespace characters and the result still needs to show that.
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),'')