i have a stored procedure, on a sql server, with the following code:
USE [MASS]
GO
/****** Object: StoredProcedure [dbo].[DossierEmailSend] Script Date: 05/11/2019 17:36:13 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[DossierEmailSend]
AS
--Create a holding table for the dossiers that met the criteria
DECLARE #dossiers TABLE (col1 varchar(100), col2 varchar(100), col3 varchar(100), col4 varchar(100));
--Insert the dossiers that met the criteria
INSERT INTO #dossiers
SELECT no, nome, obrano, convert(varchar,datafinal) col4
FROM bo
WHERE nmdos LIKE '%preço%'
AND datafinal = DATEADD(day, -1, CONVERT(date, GETDATE()))
--Create a row check to determine whether to send the email or not
DECLARE #rows int;
SET #rows = (SELECT COUNT(*) FROM #dossiers)
--Set the body elements
DECLARE #message varchar(1000);
-- declare the xml data to pass to the HTML body
DECLARE #xml NVARCHAR(MAX);
-- body will hold the HTML formatted table in the email
DECLARE #body NVARCHAR(MAX);
--Create the columns that will hold each row of data as xml
SET #xml = CAST(( SELECT col1 AS 'td','',col2 AS 'td','', col3 AS 'td','', col4 AS 'td'
FROM #dossiers
FOR XML PATH('tr'), ELEMENTS ) AS NVARCHAR(MAX))
--Set the HTML for the body
SET #body ='<html><body><H3>Dossier Info</H3>
<table border = 1>
<tr>
<th> Num </th> <th> Nome </th> <th> Dossier </th> <th> Data de Fecho </th></tr>'
--Stitch everything together, appending the HTML table
SET #body = #body + #xml +'</table></body></html>'
SET NOCOUNT ON
--Check if any dossiers met the criteria
IF #rows > 0
BEGIN
--Send the email and append the data table to the body
EXEC dbo.uspSendEmail 'Encerramento Dossier Preços', 'ssantos#mass.pt', #body, NULL, 'filipeferreira#mass.pt'
SET NOCOUNT OFF
END
to run this procedure, i created a job, that fetches this procedure, but the fact is that it's not running. on the job properties, i have set:
on success action quit the job reporting success and on failure action the same thing. i really don't know if the mistake is here, any thoughts on this guys?
Related
I have created SSIS package which has 1 SQL task (stored procedure which returns list of below 4 columns. How will achieve the following table to be sent through email. Immediate Next task here what I would do is create another stored procdure which accepts the result set from 1st stored proc through another Sql task and 2nd stored proc contains msdb_SendDBemail call . Is there any better approach
Nice thread on stack exchange: Need to Send a formatted HTML Email via Database Mail in Sql Server 2008 R2
It has an answer with a code of stored procedure dbo.HtmlTable that can generate HTML for further use in database mail:
CREATE table ##foo (bar1 int, bar2 varchar(20), bar3 datetime)
INSERT into ##foo values (1, 'Abcdef', getdate())
INSERT into ##foo values (2, 'Ghijkl', '05/05/15')
DECLARE #tableHtml varchar(max)
EXEC dbo.HtmlTable
'##foo',
#tableHtml output
PRINT #tableHtml
#tableHtml will contain html that renders into:
You can try something like this to get data in tabular format. To execute row by row you need to implement a cursor like this.
CREATE PROCEDURE [dbo].[SendNewDeviceInfoToEmployee]
AS
BEGIN
SET NOCOUNT ON
DECLARE #Mbody VARCHAR(MAX),
#Sub VARCHAR(500),
#EmpEmailPwdId BIGINT,
#Emp_nm VARCHAR(150),
#ToEmailid VARCHAR(150),
#NewEmailId VARCHAR(150),
DECLARE #Recipients VARCHAR(max)
DECLARE SendautoLoginDtl CURSOR FOR
SELECT EmpEmailPwdId, EmpName, ToEmailid, NewEmailId, EmpPassword
FROM EmployeeEmailIdPassword WHERE ISNULL(Freeze,'N') = 'N' AND ISNULL(IsMailSent,'N') = 'N' AND ISNULL(ToEmailId,'') <> '' AND ISNULL(NewEmailId,'') <> ''
ORDER BY EmpEmailPwdId
OPEN SendautoLoginDtl;
FETCH NEXT FROM SendautoLoginDtl INTO #EmpEmailPwdId, #emp_nm, #ToEmailid, #NewEmailId
WHILE( ##FETCH_STATUS = 0 )
BEGIN
SET #xml = CAST(( SELECT [Rank] AS 'td','',[Player Name] AS 'td','', [Ranking Points] AS 'td','', Country AS 'td'
FROM #Temp
ORDER BY Rank
FOR XML PATH('tr'), ELEMENTS ) AS NVARCHAR(MAX))
SET #Mbody =N'<html><body><H3>Tennis Rankings Info</H3>
<table border = 1>
<tr>
<th> Rank </th> <th> Player Name </th> <th> Ranking Points </th> <th> Country </th></tr>'
SET #body = #body + #xml +'</table></body></html>'
SET #sub='Your New Device Details - ' + #emp_nm
set #Recipients = #ToEmailid
EXEC msdb.dbo.sp_send_dbmail '<YourDBMailProfileName>' ,
#recipients = #Recipients ,
#copy_recipients = #NewEmailId,
#subject = #sub ,
#body = #Mbody ,
#body_format = 'HTML'
--Update table if required
UPDATE <YourTable>
SET IsMailSent = 'Y'
WHERE EmpEmailPwdId = #EmpEmailPwdId
FETCH NEXT FROM SendautoLoginDtl INTO #EmpEmailPwdId, #emp_nm, #ToEmailid, #NewEmailId, #EmpPassword
END
CLOSE SendautoLoginDtl;
DEALLOCATE SendautoLoginDtl;
END
You can learn about cursor here.
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;
I've written a stored procedure which is called on a link which provides a date value every time and #cg is NULL that time to filter the result on a particular date.
DECLARE #return_value int
EXEC #return_value = [dbo].[Get_Mydata]
#cg = NULL,
#tosearch = '15-05-2014'
SELECT 'Return Value' = #return_value
GO
And after first execution of the stored procedure, it gives some results and using same stored procedure.
I need to filter result by passing below parameter so this time #cg is NOT NULL.
DECLARE #return_value int
EXEC #return_value = [dbo].[Get_Mydata]
#cg = 'CUSTOMER NAME',
#tosearch = 'manish'
SELECT 'Return Value' = #return_value
GO
I'm not able to figure how should I create a dynamic where clause and add it to existing query as well as how to pass value to same parameter which already been passed as date.
More like first getting results for a particular date and then applying like filter on that result. I cannot pass different parameter that's Front end developers requirement.
This is my stored procedure and table data here. http://sqlfiddle.com/#!3/bb917
create proc Get_Mydata
(
#cg varchar(50),
#tosearch varchar(50)
)
as
begin
set nocount on
declare #sqlquery nvarchar(max)
set #sqlquery = N'select q_no, trandate, cust_name from testsp where CONVERT(Date, trandate, 103) = CONVERT(Date, ''' + #tosearch + ''' ,103)';
create table #temp1
(
q_no int,
trandate datetime,
cust_name varchar(50)
)
insert into #temp1(q_no, trandate, cust_name)
exec (#sqlquery)
select * from #temp1 as T;
set nocount off
end
What I have understood is that you want stored procedure to filter results on Date column when you pass null to #cg param and you want to filter results on Cust_name when you pass string 'Cust_Name' to your #Cg Param.
It should be fairly simple, But in any case you do not need a temp table to get the results back its just an over kill of a fairly simple query.
I would do something like this....
Pass the column name to #ColumnName Parameter, and your value to #tosearch parameter. It will build the query depending on what values you pass.
Make sure when you pass a value(Column Name) to #ColumnName.
create proc Get_Mydata
(
#ColumnName varchar(50),
#tosearch varchar(50)
)
as
begin
set nocount on;
declare #sqlquery nvarchar(max);
set #sqlquery = N' select q_no, trandate, cust_name '
+ N' from testsp '
+ N' where ' + QUOTENAME(#ColumnName) + N' = '
+ CASE
WHEN #ColumnName = 'trandate'
THEN N' CAST(#tosearch AS DATE)'
WHEN #ColumnName = 'cust_name'
THEN N' #tosearch'
ELSE N'' END
EXECUTE sp_executesql #sqlquery
,N'#tosearch varchar(50)'
,#tosearch
set nocount off;
end
I have two very similar tables in our database, and I need to write a stored procedure for my Visual Studio 2010 Web Application to read the data from one of these tables given a table number.
Currently, we only have two tables to select from, but I can see this growing to more as this project grows.
This is sort of what I am trying to do, but this code is not correct:
PROCEDURE [dbo].[spGetData]
#tableID int
AS
BEGIN
SET NOCOUNT ON;
declare #col1 nvarchar(50), #table nvarchar(50)
set #col1=case when #tableID=1 then 'SMRequestID' else 'WHRequestID' end
set #table=case when #tableID=1 then 'SMRequest' else 'WHRequest' end
select #col1 as 'Request', WorkOrder, PartNumber, Qty, EmployeeID
from #table
END
Basically, the ColumnName and TableName depend on the #tableID parameter that will be passed in.
How would I go about doing that?
Note: My searches are not turning up anything related, but I am a C# developer and not a database developer. I imagine this has been asked before, it is just I am not using the right keywords.
Although I think Mark is quite correct given the small number of tables and simplicity of your queries, here is a dynamic sql example that passes both the table and column names:
CREATE PROCEDURE spGetData
(
#TableName nvarchar(128),
#ColumnName nvarchar(128)
)
AS
BEGIN
SET NOCOUNT ON;
DECLARE #SQL nvarchar(4000)
SET #SQL = 'SELECT ' + #ColumnName + ', as Request, WorkOrder, PartNumber, Qty, EmployeeID FROM ' + #TableName
EXEC sp_executesql #SQL
END
You can call it as follows:
exec spGetData 'SMRequest', 'SMRequestID'
exec spGetData 'WHRequest', 'WHRequestID'
One option would be to use a conditional based upon the ID and put the code for a specific table in each section for the table.
I prefer this method to get away from the dynamic sql and allow the database server to get a fighting chance to optimize the thing for speed reasons by precompiling.
NOTE: database servers are pretty bad at string manipulation (create dynamic sql) in general.
EDIT1: EXAMPLE
FOR INSTANCE: THIS SQL
declare #mytest varchar(5)
set #mytest = 'PROCS'
IF #mytest = 'PROCS'
BEGIN /* STORED PROCS */
SELECT DISTINCT
o.name AS ObjectName_StoredProcedure
FROM sysobjects as o
WHERE o.xtype = 'P'
END
ELSE
IF #mytest = 'DEFAULT'
BEGIN
SELECT DISTINCT
o.name AS ObjectName_StoredProcedure
FROM sysobjects as o
WHERE o.xtype = 'D'
END
gives you the store procedure names or the default constraints depending on what you pass to the parameter.
EDIT2: Based on OP code:
CREATE PROCEDURE [dbo].[spGetData]
(#tableID int )
AS
BEGIN
SET NOCOUNT ON;
IF #tableID = 1
BEGIN
SELECT SMSRequestId AS 'Request',
WorkOrder, PartNumber, Qty, EmployeeID
FROM SMRequest
END
IF #tableID = 2
BEGIN
SELECT WHRequestID AS 'Request',
WorkOrder, PartNumber, Qty, EmployeeID
FROM WHRequest
END
END
Do it with dynamic SQL:
PROCEDURE [dbo].[spGetData]
#tableID int
AS
BEGIN
SET NOCOUNT ON;
declare #col1 nvarchar(50), #table nvarchar(50), #cmd nvarchar(400)
set #col1=case when #tableID=1 then 'SMRequestID' else 'WHRequestID' end
set #table=case when #tableID=1 then 'SMRequest' else 'WHRequest' end
#cmd = "select " + #col1 + " as 'Request', WorkOrder, PartNumber, Qty, EmployeeID from " + #table
EXEC(#cmd)
END
I am writing a stored procedure which collects all changes that were happend in a table for a given date and would like to send recordset to an administrator via email from SQL Batch Job.
Now untill now, I couldn't figure out is how to send recordset in an email body. Is it possible to construct email body based on the recordset obtained from some tsql logic.
Any help is appriciated
Thanks
TheITGuy
Look into the sp_send_dbmail procedure, which allows you to execute a query and send the results in the e-mail body or as a file attachment.
This might provide you some impetus:
CREATE TABLE #Temp
(
[Rank] [int],
[Player Name] [varchar](128),
[Ranking Points] [int],
[Country] [varchar](128)
)
INSERT INTO #Temp
SELECT 1,'Rafael Nadal',12390,'Spain'
UNION ALL
SELECT 2,'Roger Federer',7965,'Switzerland'
UNION ALL
SELECT 3,'Novak Djokovic',7880,'Serbia'
DECLARE #xml NVARCHAR(MAX)
DECLARE #body NVARCHAR(MAX)
SET #xml = CAST(( SELECT [Rank] AS 'td','',[Player Name] AS 'td','',
[Ranking Points] AS 'td','', Country AS 'td'
FROM #Temp ORDER BY Rank
FOR XML PATH('tr'), ELEMENTS ) AS NVARCHAR(MAX))
SET #body ='<html><body><H3>Tennis Rankings Info</H3>
<table border = 1>
<tr>
<th> Rank </th> <th> Player Name </th> <th> Ranking Points </th> <th> Country </th></tr>'
SET #body = #body + #xml +'</table></body></html>'
EXEC msdb.dbo.sp_send_dbmail
#profile_name = 'SQL ALERTING', -- replace with your SQL Database Mail Profile
#body = #body,
#body_format ='HTML',
#recipients = 'bruhaspathy#hotmail.com', -- replace with your email address
#subject = 'E-mail in Tabular Format' ;
DROP TABLE #Temp
The firm I work for requires the name/value pair to be on separate lines rather than in a table. While my solution could use some tuning, after much work, I came up with a solution with css formatting. I can't figure out why, however, the width of the NAME column isn't 100px, as I have requested.
The special characters are < alt >+0182, < alt >+0183 and < alt >+0185, respectively.
I will continue to strive for a more elegant solution without so many replace functions but the firm is more concerned with a 'now' solution than an elegant one. Feedback/improvements would be appreciated.
The email arrives (in Outlook) formatted as such, which is our firm's preference:
Tennis Rankings Info
Rank: 1
Player Name: Rafael Nadal
Points: 12390
Country: Spain
Rank: 2
Player Name: Roger Federer
Points: 7965
Country: Switzerland
Rank: 3
Player Name: Novak Djokovic
Points: 7880
Country: Serbia
Here is my solution:
CREATE TABLE #Temp
(
[Rank] [int],
[Player Name] [varchar](128),
[Ranking Points] [int],
[Country] [varchar](128)
)
INSERT INTO #Temp
SELECT 1,'Rafael Nadal',12390,'Spain'
UNION ALL
SELECT 2,'Roger Federer',7965,'Switzerland'
UNION ALL
SELECT 3,'Novak Djokovic',7880,'Serbia'
DECLARE #xml NVARCHAR(MAX)
DECLARE #body NVARCHAR(MAX)
SET #xml = CAST(( SELECT '¶Rank:·º' + convert(varchar, [Rank]) AS 'br','','¶Player Name:·º' +[Player Name] AS 'br','',
'¶Points:·º' + convert(varchar, [Ranking Points]) AS 'br','', '¶Country:·º' + Country AS 'br'
FROM #Temp ORDER BY Rank
FOR XML PATH('br'), ELEMENTS ) AS NVARCHAR(MAX))
SET #body ='<html><head><style type=''text/css''>body{font-family:tahoma;font-size:9pt;}.h{width:100px;}</style></head><body><H3>Tennis Rankings Info</H3>'
SET #body = #body + #xml +'</body></html>'
set #body = replace(#body, '</br>', '<br />')
set #body = replace(#body, '<br><br>', '<p>')
set #body = replace(#body, '<br>', '')
set #body = replace(#body, '<br /><br />', '</p>')
set #body = replace(#body, '¶', '<span class=''h''>')
set #body = replace(#body, '·', '</span>')
set #body = replace(#body, 'º', ' ')
--select #body
EXEC msdb.dbo.sp_send_dbmail
#profile_name = 'DBMail', -- replace with your SQL Database Mail Profile
#body = #body,
#body_format ='HTML',
#recipients = 'xxx#xxx.com', -- replace with your email address
#subject = 'E-mail in Tabular Format' ;
DROP TABLE #Temp