sp_send_dbmail - Assistance please - sql

SQL newbie. I have several jobs sending query results via email, all working fine. I'm having trouble with this last one and am not sure what is wrong. The dbmailprofile works fine and the receipients are fine. The query works if I run it in SSMS but it doesn't work if I try to create a email job. I changed the #recipients to a generic term and change the query to not show anything specific. Any help is appreciated, thanks.
USE msdb
EXECUTE AS USER = 'dbo'
EXEC msdb.dbo.sp_send_dbmail
#profile_name = 'dbmailprofile',
#recipients = 'username#someone.com',
#query = ' SELECT A.DOCNUMBER as DocumentNumber,P.DOCNAME as DocumentName,A.TYPIST as UserSystemID,PP.USER_ID as UserID,PP.FULL_NAME as UserFullName,A.ACTIVITY_TYPE as ActivityCode,
AT.DESCRIPTION as ActivityDescription, CAST(DATEADD(mi, DATEDIFF(mi, GETUTCDATE(), GETDATE()), START_DATE) AS varchar(64))
AS 'ActivityTime In Local Time'
FROM DOCSADM.ACTIVITYLOG A
JOIN DOCSADM.PROFILE P
ON A.DOCNUMBER=P.DOCNUMBER
JOIN DOCSADM.PEOPLE PP
ON A.TYPIST=PP.SYSTEM_ID
JOIN DOCSADM.ACT_TYPES AT
ON A.ACTIVITY_TYPE=AT.VALUE
WHERE PP.USER_ID = 'USER'
AND A.START_DATE
> DATEADD(DD, -1,GETDATE())
GROUP BY A.DOCNUMBER,P.DOCNAME,A.TYPIST,PP.USER_ID,PP.FULL_NAME,
A.ACTIVITY_TYPE,AT.DESCRIPTION,A.START_DATE ORDER BY A.DOCNUMBER DESC, A.START_DATE DESC;',
#subject = 'Activity Report',
#body = 'The Stored Procedure completed sucessfully' ,
When I run this, I get the error 'Incorrect syntax near 'ActivityTime'

Related

Notifications for SQL Job when a step fails

Trying to find out if there is a way to setup email notifications when just 1 (or more) steps fail on a sql job. I have a job with 9 steps, but each step needs to be set to continue to next step even if it fails. So even when a step fails, because I need it to go to the next step its not set to "report failure". As SQL Server Agent does not have an option for "Report failure and go to next step" I am wondering if anyone has any workarounds for getting a notification
You can add an additional job step to query the msdb tables for steps that failed. After this, the sp_send_dbmail stored procedure can be used to send an email with the errors if any occurred. The run_date column of SYSJOBHISTORY is an int column, so the date will be along the format of YYYYMMDD. The filter below on the run_status column will apply to individual steps regardless of the overall job outcome, with 0 indicating a status of failed.
DECLARE #JobExecutionDate INT
--current date
SET #JobExecutionDate = CAST(CONVERT(VARCHAR(8),GETDATE(),112) AS INT)
--check if there were any errors first
IF EXISTS (SELECT h.instance_id
FROM MSDB.DBO.SYSJOBHISTORY h
INNER JOIN MSDB.DBO.SYSJOBS j ON h.job_id = j.job_id
INNER JOIN MSDB.DBO.SYSJOBSTEPS s ON j.job_id = s.job_id AND h.step_id = s.step_id
WHERE h.run_status = 0 AND h.run_date = #JobExecutionDate AND j.name = 'YourJobName')
BEGIN
DECLARE #Title VARCHAR(50)
SET #Title = CONCAT(CONVERT(VARCHAR(12), CAST(GETDATE() AS DATE), 109), ' Job Error Email')
EXEC msdb.dbo.sp_send_dbmail
#profile_name = 'Your Database Mail Profile',
#recipients = 'ExampleEmail#Domain.com',
#query = 'SELECT j.[name] AS JobName,
s.step_name AS StepName,
h.run_date AS RunDate,
h.run_time AS RunTime,
h.sql_severity As ErrorSeverity,
h.message AS ErrorMessage
FROM MSDB.DBO.SYSJOBHISTORY h
INNER JOIN MSDB.DBO.SYSJOBS j ON h.job_id = j.job_id
INNER JOIN MSDB.DBO.SYSJOBSTEPS s ON j.job_id = s.job_id AND h.step_id = s.step_id
WHERE h.run_status = 0 AND h.run_date = CAST(CONVERT(VARCHAR(8),GETDATE(),112) AS INT) AND j.name = ''YourJobName''
',
#query_result_no_padding = 1,
#subject = #Title ;
END

SQL Server 2008 R2 match counts

I have a SQL query that checks when a stored procedure was last run, from that date it gathers all the units that were purchased between that date and today's date and compares it to another number. If they match it sends an email saying the two number match and executes the rest of the stored procedure. However, when it runs I constantly get 0 for the number of accounts, when it should be a value greater than 0 daily:Here is my code:
DECLARE #UnitsPurchased int
DECLARE #WelcomeLetterGenerated int
DECLARE #LastSuccesfulRunTime datetime
SET #LastSuccesfulRunTime = (select cast(run_datetime as DATE) from apsllc_v2.dbo.LastSuccesfulRunDate)
SET #UnitsPurchased = (SELECT COUNT(*) FROM rsbi.dbo.loans as l
where rsbi.dbo.fn_Convert_Paradata_Birth_Date(l.Unit_PURDATE) between #LastSuccesfulRunTime
AND getDate() and l.LN_CLASS in (58,59)) -- Shows the number of units that were purchased yesterday
SET #WelcomeLetterGenerated = ( SELECT COUNT(*) FROM apsllc_v2.dbo.ApsUpload ap where ap.FormNumber IN(1100,1150) ) -- Shows how many welcome letters were generated today
if #UnitsPurchased <> #WelcomeLetterGenerated
begin
EXEC msdb.dbo.sp_send_dbmail
#recipients = N''
, #body = ' '
, #subject = 'Welcome Letter Counts do not Match'
, #profile_name = 'Email_Profile_01'
return
end
ELSE if #UnitsPurchased = #WelcomeLetterGenerated --or if
begin
EXEC msdb.dbo.sp_send_dbmail
#recipients = N''
, #body = ' '
, #subject = 'Welcome Letter Counts Match'
, #profile_name = 'Email_Profile_01'
end

SQL Email based on query

I have set up SQL server to email and have successfully. I am trying to send an email with the following query:
select count(*) from report queue
I would like an email sent when count is > 10.
I have never done a SQL stored procedure before.
SELECT COUNT(*) AS ct
FROM report_queue
HAVING ct > 10
Can you try this?
select email from report queue group by email having count(*)>10
Another alternative;
IF ((SELECT COUNT(*) FROM [report queue]) > 10)
SELECT * FROM [report queue]
CREATE PROCEDURE [dbo].[email_report] (#recipients nvarchar(max), #subject nvarchar(max) = '', #body nvarchar(max) = '')
AS
BEGIN
IF (SELECT COUNT(*) FROM [report_queue]) > 10
EXEC [msdb].[dbo].[sp_send_dbmail]
#recipients = #recipients,
#subject = #subject,
#body = #body;
END
More details available here: sp_send_dbmail (Transact-SQL)

Cannot specify an index or locking hint for a remote data source SQL Server 2005

I have this query which involves a table from another server:
select count(serialno), max(convert(varchar(10),Crtd_DateTime,101))
from tblSBox tsb (nolock)
inner join tblMBox tmb (nolock) on tsb.idMaster = tmb.idMaster
inner join [server_2].fdb.dbo.sns_in_out sio
on tsb.serialno = sio.lotsernbr and invtMult='-1' and RefNbr like 'I%'
where tmb.WO=34612
but this query is taking forever, and I cannot specify an index or locking hint for a remote data source, so I looked into the web and I found out that I can use this:
SELECT * FROM OpenQuery(server, 'Select * from sometable with (nolock)')
Which works fine, but as you can see I have a link between tsb.serialno and sio.lotsernbr, and when I place all that inside the '' like the following:
select serialno,
(SELECT *
FROM OpenQuery([server_2], 'select convert(varchar(10), Crtd_DateTime, 101)
from fdb.dbo.sns_in_out sio (nolock)
where (tsb.serialno = sio.lotsernbr
and invtMult=''-1'' and RefNbr like ''I%'')')) as crtDate
from tblSBox tsb (nolock)
inner join tblMBox tmb (nolock) on tsb.idMaster = tmb.idMaster
where tmb.WO=34612
I get this error:
[OLE/DB provider returned message: Deferred prepare could not be
completed.]
Msg 8180, Level 16, State 1, Line 1
Statement(s) could not be prepared.
Msg 4104, Level 16, State 1, Line 1
The multi-part identifier "tsb.serialno" could not be bound.
Any idea of how to accomplish this?
If you want to run queries with (NOLOCK) on a remote server, create a stored procedure or view on the remote server and apply the locking hint there.
If you have no access to the remote server, you could pull the data first by executing something like this through a linked server (I'll assume your linked server is called server_2):
CREATE TABLE #loc (lotsernbr INT, dt DATETIME);
INSERT #loc
EXEC [server_2].fdb..sp_executesql 'SELECT lotsernbr, Crt_DateTime
FROM dbo.sns_in_out WITH (NOLOCK)
WHERE invtMult=''-1'' AND RefNbr LIKE ''I%'';';
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; -- much better than nolock on every table
SELECT tsb.serialno, crtDate = CONVERT(CHAR(10), loc.dt, 101)
FROM tblSBox AS tsb
INNER JOIN #loc AS loc
ON tsb.serialno = loc.lotsernbr
INNER JOIN tblMBox AS tmb
ON tsb.idMaster = tmb.idMaster
WHERE tmb.WO = 34612;
Now you can join against the local #temp table. The difference may be negligible but it may be significant. If this brings across a lot of rows and you only need a few, you may want to do it slightly differently: build your IN list dynamically and pass it to the other server, e.g.
DECLARE #sql NVARCHAR(MAX);
SET #sql = N'';
SELECT #sql = #sql + ',' + CONVERT(VARCHAR(12), serialno)
FROM tblSBox AS tsb
INNER JOIN tblMBox AS tmb
ON tsb.idMaster = tmb.idMaster
WHERE tmb.WO = 34612
GROUP BY serialno; -- to avoid dupes
SET #sql = N'SELECT serialno = lotsernbr, crtDate = CONVERT(CHAR(10), Crt_Datetime, 101)
FROM fdb.dbo.sns_in_out WITH (NOLOCK)
WHERE lotsernbr IN (' + STUFF(#sql, 1, 1, N'') + ');'
-- now you don't need the join, since you are only outputting
-- the two columns:
EXEC [server_2].fdb..sp_executesql #sql;

T-Sql Dynamic Query String Limit

I am getting a weird exception saying "
"
Msg 203, Level 16, State 2, Line 53
The name 'SELECT
ISNULL(ESP.ID,-1) AS 'PayScaleID',
ISNULL(E.Prefix,'') + ISNULL(E.SerialNo,0) AS 'Token number',
ISNULL(E.FirstName,'')+' '+ ISNULL(E.MiddleName,'')+' '+ISNULL(E.LastName,'') AS 'Employee name',
ISNULL(E.CostCentreCode,'') AS 'Cost centre code',
ESP.TotalPresentDays AS 'Present days',
ESP.TotalWeeklyOffDays AS 'Week offs',
ESP.TotalPaidHolidays AS 'Paid holiDays',
ESP.TotalAbsentDays AS 'Absent days',
ESP.ArrearDays AS 'Arrear days',
ESP.OTHours AS 'OTHours',
ESP.TotalPaidAmount AS 'Total Amount',
MAD.Name AS 'Allowance' ,
X.Amount
INTO #temp
FROM
(
SELECT
-1 AS 'BillingI' is not a valid identifier."
I am executing the following query.
"
{
DECLARE #sql AS VARCHAR(8000)
SET #sql = 'SELECT
ISNULL(ESP.ID,-1) AS ''PayScaleID'',
ISNULL(E.Prefix,'''') + ISNULL(E.SerialNo,0) AS ''Token number'',
ISNULL(E.FirstName,'''')+'' ''+ ISNULL(E.MiddleName,'''')+'' ''+ISNULL(E.LastName,'''') AS ''Employee name'',
ISNULL(E.CostCentreCode,'''') AS ''Cost centre code'',
ESP.TotalPresentDays AS ''Present days'',
ESP.TotalWeeklyOffDays AS ''Week offs'',
ESP.TotalPaidHolidays AS ''Paid holiDays'',
ESP.TotalAbsentDays AS ''Absent days'',
ESP.ArrearDays AS ''Arrear days'',
ESP.OTHours AS ''OTHours'',
ESP.TotalPaidAmount AS ''Total Amount'',
MAD.Name AS ''Allowance'' ,
X.Amount
INTO #temp
FROM
(
SELECT
-1 AS ''BillingID'',
ESP.ID AS ''EmployeeSalaryPaidID'',
MAd.ID AS ''AllowanceID'',
ESPD.PaidAmount AS ''Amount''
FROM Employee_SalaryPaid ESP
INNER JOIN Employee_SalaryPaidDetails ESPD ON ESPD.EmployeeSalaryPaidID = ESP.ID
INNER JOIN Employee E ON E.ID = ESP.EmployeeID
INNER JOIN Master_AllowanceDeduction MAD ON MAD.ID = ESPD.AllowanceDeductionID
WHERE ESP.YearAndMonth =201104
UNION ALL
SELECT
CBR.ID AS ''BillingID'',
CBRD.EmployeeSalaryPaidID,
CBRD.AllowanceDeductionID AS ''AllowanceID'',
CBRD.Amount AS ''Amount''
FROM Company_BillRaised CBR
INNER JOIN Company_BillRaisedDetails CBRD ON CBRD.BillRaisedID = CBR.ID
WHERE CBR.MonthYear =201104
)X
INNER JOIN Master_AllowanceDeduction MAD ON MAD.ID = X.AllowanceID
INNER JOIN Employee_SalaryPaid ESP ON ESP.ID =X.EmployeeSalaryPaidID
INNER JOIN Employee E ON E.ID= ESP.EmployeeID
INNER JOIN dbo.vw_CompanyEmployeeIDs CE ON CE.EmployeeID = E.ID
WHERE CE.BranchID =73
DROP TABLE #temp'
EXEC #sql
}
I cannot understand what exactly the problem is? Do we have some limits of characters while executing Dynamic Sql like I am doing. I tried printing what I am getting in #Sql, I can get the results what I am looking for. But when I go like this using EXEC #Sql it gives me the error.
Any suggestions?
Try
Declaring #sql as nvarchar(max)
then
exec sp_executesql #sql
instead of
exec #sql
Executing dynamic sql with just exec is very limited. See this link http://www.sommarskog.se/dynamic_sql.html.
Try changing your last line to EXEC (#sql).
Execute a character string
{ EXEC | EXECUTE }
( { #string_variable | [ N ]'tsql_string' } [ + ...n ] )
[ AS { LOGIN | USER } = ' name ' ]
[;]
Source:
EXECUTE (Transact-SQL)
You can use:
Execute or exec: EXEC (#sql)
The system stored procedure sp_execute. Benefits: can use additional parameters in the syntax and validate the data types before execution: execute sp_execute #sql