Ive got the next query, and the problem is that it work for mail 1 and 2, but not to 3 and 4 (and 3,4 exists in the select table). some idea?
[I looked for help and i guess that the right way to do it, it's cursor, but I did not make it also with cursor).
ALTER PROCEDURE [DBMAIL].[Mail_FOR_USER]
#Mail_1 NVARCHAR (100),
#Mail_2 NVARCHAR (100),
#Mail_3 NVARCHAR (100),
#Mail_4 NVARCHAR (100)
AS
BEGIN TRY
EXEC sp_configure 'show advanced', 1;
RECONFIGURE;
EXEC sp_configure 'show advanced options', 1;
RECONFIGURE;
EXEC sp_configure 'Database Mail XPs', 1;
RECONFIGURE
DECLARE
#ID INT=1,
#RN INT,
#xCol XML,
#XML_Creation_Date DATETIME ,
#File_Path NVARCHAR(200),
#USER_1 NVARCHAR(100),
#USER_2 NVARCHAR(100),
#USER_3 NVARCHAR(100),
#USER_4 NVARCHAR(100),
#Recipients_List NVARCHAR(MAX);
---============================================
WHILE #ID<= (SELECT MAX (ID) FROM Report_FOR_Users)
BEGIN
SELECT [ID], [RN], [xCol], [XML_Creation_Date], [File_Path], [USER_1], [USER_2], [USER_3], [USER_4]
FROM Report_FOR_Users WHERE ID=#ID
SET #File_Path= (SELECT File_Path FROM Report_FOR_Users WHERE ID=#ID)
SET #Mail_1= CASE
WHEN (SELECT USER_1 FROM Report_FOR_Users WHERE ID=#ID) IS NULL THEN ' '
ELSE #Mail_1
END
SET #Mail_2= CASE
WHEN (SELECT USER_2 FROM Report_FOR_Users WHERE ID=#ID) IS NULL THEN ' '
ELSE #Mail_2
END
SET #Mail_3= CASE
WHEN (SELECT USER_3 FROM Report_FOR_Users WHERE ID=#ID) IS NULL THEN ' '
ELSE #Mail_3
END
SET #Mail_4= CASE
WHEN (SELECT USER_4 FROM Report_FOR_Users WHERE ID=#ID) IS NULL THEN ' '
ELSE #Mail_4
END
SET #Recipients_List= #Mail_1+';'+#Mail_2+';'+#Mail_3+';'+#Mail_4
EXEC msdb.dbo.sp_send_dbmail
#profile_name = 'SEmailProfile',
#recipients = #Recipients_List,
#body = 'ola?',
#subject = 'Hopa',
#file_attachments = #File_Path;
SET #ID=#ID+1
END
ALTER PROCEDURE [DBMAIL].[Mail_FOR_USER]
(
#Mail_1 NVARCHAR(100),
#Mail_2 NVARCHAR(100),
#Mail_3 NVARCHAR(100),
#Mail_4 NVARCHAR(100)
)
AS BEGIN
SET NOCOUNT ON;
DECLARE
#UserID INT
, #File_Path NVARCHAR(200)
, #USER_1 NVARCHAR(100)
, #USER_2 NVARCHAR(100)
, #USER_3 NVARCHAR(100)
, #USER_4 NVARCHAR(100)
DECLARE cur CURSOR FAST_FORWARD READ_ONLY LOCAL FOR
SELECT ID, File_Path
FROM dbo.Report_FOR_Users
OPEN cur
FETCH NEXT FROM cur INTO #UserID, #File_Path
WHILE ##FETCH_STATUS = 0 BEGIN
SELECT
#USER_1 = CASE WHEN USER_1 IS NOT NULL THEN #Mail_1 END
, #USER_2 = CASE WHEN USER_2 IS NOT NULL THEN #Mail_2 END
, #USER_3 = CASE WHEN USER_3 IS NOT NULL THEN #Mail_3 END
, #USER_4 = CASE WHEN USER_4 IS NOT NULL THEN #Mail_4 END
FROM dbo.Report_FOR_Users
WHERE ID = #ID
SELECT #Recipients_List = STUFF((
SELECT ';' + val
FROM (
VALUES (#USER_1), (#USER_2), (#USER_3), (#USER_4)
) t(val)
WHERE t.val IS NOT NULL
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 1, '')
EXEC msdb.dbo.sp_send_dbmail
#profile_name = 'SEmailProfile',
#recipients = #Recipients_List,
#body = 'ola?',
#subject = 'Hopa',
#file_attachments = #File_Path
FETCH NEXT FROM cur INTO #UserID, #File_Path
END
CLOSE cur
DEALLOCATE cur
END
Related
I have a database in SQL Server that has a user table with 3 columns: name, date of birth and email.
I have a stored procedure that goes through this table looking for who is having a birthday today, and sends him a congratulatory email, so far it works at 100.
However, I want to add within the same procedure that I send an email to all the users of the database (except the one with a birthday), notifying them that x person are having a birthday today.
This is my current SQL Server code:
CREATE PROCEDURE spSendEmail
AS
DECLARE #email nvarchar(128)
DECLARE #name nvarchar(128)
DECLARE #Date date
SELECT
GETDATE(),
MONTH(GETDATE()), DAY(GETDATE()), YEAR(GETDATE())
DECLARE email_cursor CURSOR FOR
SELECT u.name, u.email
FROM dbo.users u
WHERE MONTH(u.dateofbirth) = MONTH(GETDATE())
AND DAY(u.dateofbirth) = DAY(GETDATE())
OPEN email_cursor
FETCH NEXT FROM email_cursor INTO #name, #email
WHILE ##FETCH_STATUS = 0
BEGIN
PRINT #email
DECLARE #subject nvarchar(255)
DECLARE #Bodytext nvarchar(512)
SET #BodyText = #Name + '' + 'we wish you happy birthday'
SET #Subject = 'Happy Birthday'
EXEC msdb.dbo.sp_send_dbmail
#profile_name = 'Birthday Alert',
#recipients = #email,
#body = #Bodytext,
#subject = #subject;
FETCH NEXT FROM email_cursor INTO #name, #email
END
CLOSE email_cursor
DEALLOCATE email_cursor
CREATE PROCEDURE spSendEmail AS
DECLARE #email nvarchar(128)
DECLARE #name nvarchar(128)
DECLARE #Date date
DECLARE #Num_Users_Having_Birthday varchar(100) = (SELECT COUNT(*) FROM dbo.users WHERE MONTH(u.dateofbirth) = MONTH(GETDATE())
AND DAY(u.dateofbirth) = DAY(GETDATE()))
SELECT
GETDATE(),
MONTH(GETDATE()), DAY(GETDATE()), YEAR(GETDATE())
DECLARE email_cursor CURSOR FOR
SELECT u.name, u.email
FROM dbo.users u
WHERE MONTH(u.dateofbirth) <> MONTH(GETDATE())
AND DAY(u.dateofbirth) <> DAY(GETDATE())
OPEN email_cursor
FETCH NEXT FROM email_cursor INTO #name, #email
WHILE ##FETCH_STATUS = 0
BEGIN
PRINT #email
DECLARE #subject nvarchar(255)
DECLARE #Bodytext nvarchar(512)
SET #BodyText = #Name
SET #Subject = 'Number of People having Birthday today:' + #Num_Users_Having_Birthday
EXEC msdb.dbo.sp_send_dbmail
#profile_name = 'Birthday Alert',
#recipients = #email,
#body = #Bodytext,
#subject = #subject;
FETCH NEXT FROM email_cursor INTO #name, #email
END
CLOSE email_cursor
DEALLOCATE email_cursor
Try this:
CREATE PROCEDURE spSendEmail
AS
BEGIN
DECLARE #email nvarchar(128)
DECLARE #name nvarchar(128)
DECLARE #has_birthday BIT
DECLARE #Date date
DECLARE #birthday_boys INT -- update this to
SELECT
GETDATE(),
MONTH(GETDATE()), DAY(GETDATE()), YEAR(GETDATE())
IF(OBJECT_ID('tempdb..users') IS NOT NULL)
DROP TABLE #users;
-- For Sql Server version >= 2016: DROP TABLE IF EXISTS #users
SELECT u.name, u.email
, IIF(MONTH(u.dateofbirth) = MONTH(GETDATE()) AND DAY(u.dateofbirth) = DAY(GETDATE()),1,0) has_birthday
INTO #users
FROM dbo.users u
--Get all birthday boys list
SELECT #birthday_boys = COUNT(u.name)
FROM #users u
WHERE has_birthday = 1
DECLARE email_cursor CURSOR FOR
SELECT u.name, u.email, u.has_birthday
FROM #users
OPEN email_cursor
FETCH NEXT FROM email_cursor INTO #name, #email, #has_birthday
WHILE ##FETCH_STATUS = 0
BEGIN
PRINT #email
DECLARE #subject nvarchar(255)
DECLARE #Bodytext nvarchar(512)
SET #BodyText = IIF(#has_birthday = 1, #Name + '' + 'we wish you happy birthday', CONCAT('Birthday boys'' count is ', #birthday_boys))
SET #Subject = IIF(#has_birthday = 1, 'Happy Birthday', 'Birthday Boys'' Count')
EXEC msdb.dbo.sp_send_dbmail
#profile_name = 'Birthday Alert',
#recipients = #email,
#body = #BodyText,
#subject = #subject
FETCH NEXT FROM email_cursor INTO #name, #email
END
CLOSE email_cursor
DEALLOCATE email_cursor
IF(OBJECT_ID('tempdb..users') IS NOT NULL)
DROP TABLE #users;
-- For Sql Server version >= 2016: DROP TABLE IF EXISTS #users
END
There is a procedure in which an Excel file is created, the result of the selection is saved in it. This file is attached to the letter and sent by mail. But the problem is that the file is created and sent empty. Manually everything works, but not together.
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[sp_sendMail]
#SID INT,
#EMAIL VARCHAR(512),
#CUR INT
AS
BEGIN
SET NOCOUNT ON;
DECLARE
#MAILID INT,
#TABLEHTML VARCHAR(MAX),
#CMD SYSNAME,
#FILENAME NVARCHAR(MAX),
#SQL NVARCHAR(MAX),
#PID INT,
#DATE_START DATE,
#DATE_END DATE
SELECT
#PID = PATIENTS_ID,
#DATE_START = DATE_START,
#DATE_END = DATE_END
FROM
TABLE
WHERE
ID = #SID
EXEC SP_EXECUTESQL N'sp_configure ''show advanced options'', 1; reconfigure; '
EXEC ('RECONFIGURE')
EXEC SP_EXECUTESQL N'sp_configure ''xp_cmdshell'', 1; reconfigure;'
EXEC ('RECONFIGURE')
SET #FILENAME = 'D:\' + CAST(#SID AS VARCHAR) + '_' + REPLACE(CONVERT(VARCHAR, GETDATE(), 104), '.', '') + '_' + CAST(#CUR AS VARCHAR) + '.xlsx'
SET #CMD = 'copy D:\Example.xlsx ' + #FILENAME
EXEC MASTER..XP_CMDSHELL #CMD;
SET #SQL = 'INSERT INTO OPENROWSET(''Microsoft.ACE.OLEDB.12.0'',
''Excel 12.0;Database=' + #FILENAME + ';HDR=YES'',
''SELECT DATE, CODE, LABEL, CNT, CU, SCO, DISCOUNT FROM [Sheet1$]'')
SELECT
CONVERT(VARCHAR, ORDER.DATE, 104) DATE,
EMPLOYEE.CODE CODE,
EMPLOYEE.LABEL LABEL,
CAST(ORDER.CNT AS INT) CNT,
CAST(ORDER.PRICE AS MONEY) CU,
CAST(ORDER.PRICE_TO_PAY AS MONEY) SCO,
CAST(ORDER.DISCOUNT AS INT) DISCOUNT
FROM
ORDER
JOIN
EMPLOYEE ON EMPLOYEE._ID = ORDER._ID
WHERE
(CONVERT(DATE, ORDER.DATE) >= CONVERT(DATE, #DATE_START)
AND CONVERT(DATE, ORDER.DATE) <= CONVERT(DATE, #DATE_END))
AND (ORDER.ID in (#PID))
ORDER BY ORDER.DATE'
EXEC SP_EXECUTESQL
#SQL,
N'#DATE_START DATE, #DATE_END DATE, #PATID INT',
#DATE_START = #DATE_START,
#DATE_END = #DATE_END,
#PID = #PID
SET #TABLEHTML =
N'<H1>Hello!</H1>' +
N'<span>num: </span>' + CAST(#SID AS VARCHAR(MAX)) +
N'<span>, email: </span>' + CAST(#EMAIL AS VARCHAR(MAX)) +
N'<span> sent! </span>'
EXEC msdb.dbo.sp_send_dbmail
#profile_name = 'site.com',
#recipients = 'admin#site.com',
#subject = 'subj',
#body = #tableHTML,
#body_format = 'HTML',
#file_attachments = #FILENAME,
#mailitem_id = #mailid output
IF (#MAILID > 0 AND ##ERROR = 0)
UPDATE TABLE SET [SIGN] = 1, [SENT] = GETDATE(), SENDER = #CUR WHERE ID = #SID
EXEC SP_EXECUTESQL N'sp_configure ''show advanced options'', 1; reconfigure; '
EXEC ('RECONFIGURE')
EXEC SP_EXECUTESQL N'sp_configure ''xp_cmdshell'', 0; reconfigure;'
EXEC ('RECONFIGURE')
END
Yes, JGFMK was right!
If execute this code, then openrowset will be done:
if( 1 = 0)
begin
INSERT INTO OPENROWSET('Microsoft.ACE.OLEDB.12.0',
'Excel 12.0;Database=D:\file;HDR=YES',
'SELECT DATE, CODE, LABEL, CNT, CU, SCO, DISCOUNT FROM [Sheet1$]')
SELECT..
end
How to make it work by condition ?
Hi I have developed a stored procedure in which I declared the a table variable called #TEMP_TABLE but for this line
SET #SQL1 = 'UPDATE PO_STAGE set PO_STAGE.ISVALID = ''N''
FROM ERP_ADMIN.'+#STAGE_TABLE+' PO_STAGE, #TEMP_TABLE TMP
where PO_STAGE.ERP_PO_ID = TMP.ERP_POID'
exec (#SQL1)
I am getting "Must declare the table variable "#TEMP_TABLE"." error.
Please help me in this regards.Below is the code for Stored Procedure.
CREATE PROCEDURE [ERP_ADMIN].[VALIDATE_PURCHASE_ORDER]
#STAGE_TABLE nvarchar(50)
-- #errorProperty nvarchar(50) output,
-- #errorValue nvarchar(120) output
AS
BEGIN
SET NOCOUNT ON;
DECLARE #rule INTEGER
DECLARE #approvalcheckingrecord VARCHAR(200)
DECLARE #APP_VALIDFROMDATE DATETIME,
#APP_VALIDTODATE DATETIME,
#numUpdated INTEGER,
#numInserted INTEGER,
#systodate VARCHAR(160),
#SQL1 [nvarchar](1200),
#SQL2 [nvarchar](1200),
#SOUCOL [nvarchar](200)
-- SELECT #systodate = CONVERT(VARCHAR(23), ERP_ADMIN.GETCURRENTDATE(), 110) +' '+ CONVERT(VARCHAR(23), ERP_ADMIN.GETCURRENTDATE(), 108)
--SELECT #systodate = CONVERT(VARCHAR(23), GETDATE(), 110) +' '+ CONVERT(VARCHAR(23), GETDATE(), 108)
SET #SQL1 = ''
SET #SQL1 = 'SELECT ERP_SOURCE_COLUMN
FROM [ERP_ADMIN].[ERP_STAGE_PROP_MAPPING] where [ERP_SOURCE_TABLE] = '''+#STAGE_TABLE+''' and [ERP_REPORT_COLOMNS] = ''Y'''
-- PRINT #SQL1
SET #SQL2 = 'DECLARE rpt_cursor CURSOR GLOBAL FOR ' + #SQL1
exec (#SQL2)
DECLARE #SOURCE_COLOMN nvarchar(80)
SET #SOUCOL = ''
OPEN rpt_cursor
WHILE (0 = 0)
--begin of while
BEGIN
FETCH NEXT FROM rpt_cursor INTO #SOURCE_COLOMN
IF (##FETCH_STATUS = -1)
BREAK
IF (#SOUCOL = '')
SET #SOUCOL = 'convert(nvarchar(255),ISNULL('+#SOURCE_COLOMN+',''''))+'',''+'
ELSE
SET #SOUCOL = #SOUCOL + 'convert(nvarchar(255),ISNULL('+#SOURCE_COLOMN+',''''))+'',''+'
END
CLOSE rpt_cursor
DEALLOCATE rpt_cursor
PRINT #SOUCOL
DECLARE #TEMP_TABLE TABLE (
ERP_POID nvarchar(50),
ERRORCD nvarchar(50),
ERRORMSG nvarchar(120)
)
SET #SQL1 = ''
SET #SQL1 = 'SELECT ERP_SOURCE_COLUMN
FROM [ERP_ADMIN].[ERP_STAGE_PROP_MAPPING] where [ERP_SOURCE_TABLE] = '''+#STAGE_TABLE+''' and [ERP_REPORT_COLOMNS] = ''Y'''
SET #SQL1 = 'SELECT [ERP_SOURCE_TABLE]
,[ERP_SOURCE_COLUMN]
,[ERP_MANDATORY_CHECK]
,[ERP_DATA_CHECK]
,[ERP_ERROR_PROPERTY1]
,[ERP_ERROR_VALUE1]
,[ERP_ERROR_PROPERTY2]
,[ERP_ERROR_VALUE2]
FROM [ERP_ADMIN].[ERP_STAGE_PROP_MAPPING] where [ERP_SOURCE_TABLE] = '''+#STAGE_TABLE+''' and ([ERP_MANDATORY_CHECK] IN (''K'',''Y'') or [ERP_DATA_CHECK] IN (''D'',''N''))'
PRINT #SQL1
SET #SQL2 = 'DECLARE stage_cursor CURSOR GLOBAL FOR ' + #SQL1
/** DECLARE stage_cursor CURSOR LOCAL FOR
/****** Script for SelectTopNRows command from SSMS ******/
SELECT [ERP_SOURCE_TABLE]
,[ERP_SOURCE_COLUMN]
,[ERP_MANDATORY_CHECK]
,[ERP_DATA_CHECK]
,[ERP_ERROR_PROPERTY1]
,[ERP_ERROR_VALUE1]
,[ERP_ERROR_PROPERTY2]
,[ERP_ERROR_VALUE2]
FROM [ERP_ADMIN].[ERP_STAGE_PROP_MAPPING] where [ERP_SOURCE_TABLE] = '+#STAGE_TABLE+' and ([ERP_MANDATORY_CHECK] IN ('K','Y') or [ERP_DATA_CHECK] IN ('D','N')) **/
exec(#SQL2)
DECLARE #CUR_SOURCE_TABLE [nvarchar](120),
#CUR_SOURCE_COLUMN [nvarchar](120),
#CUR_MANDATORY_CHECK [nvarchar](20),
#CUR_DATA_CHECK [nvarchar](20),
#CUR_ERROR_PROPERTY1 [nvarchar](50),
#CUR_ERROR_VALUE1 [nvarchar](120),
#CUR_ERROR_PROPERTY2 [nvarchar](50),
#CUR_ERROR_VALUE2 [nvarchar](120)
OPEN stage_cursor
WHILE (0 = 0)
--begin of while
BEGIN
FETCH NEXT FROM stage_cursor INTO
#CUR_SOURCE_TABLE,
#CUR_SOURCE_COLUMN,
#CUR_MANDATORY_CHECK,
#CUR_DATA_CHECK,
#CUR_ERROR_PROPERTY1,
#CUR_ERROR_VALUE1,
#CUR_ERROR_PROPERTY2,
#CUR_ERROR_VALUE2
IF (##FETCH_STATUS = -1)
BREAK
SET #SQL1 = ''
SET #SQL2 = ''
PRINT #CUR_SOURCE_COLUMN
-- IF(#CUR_SOURCE_COLUMN = 'ERP_PO_DOCNUMBER')
IF (#CUR_MANDATORY_CHECK = 'Y' OR #CUR_MANDATORY_CHECK = 'K')
BEGIN
-- SET #SQL1 = 'SELECT ''aaa'' as column1, ERP_PO_DOCNUMBER as column2
-- from PURCHASE_ORDER_STAGE where '+ #CUR_SOURCE_COLUMN +' IS NULL'
SET #SQL1 = 'SELECT ERP_PO_ID, '''+#CUR_ERROR_PROPERTY1+''' as column1,'+#SOUCOL+'''|1| ERR_01 '''''+#CUR_ERROR_VALUE1+'''+'' or null in input Worksheet'' as column2
from [ERP_ADMIN].'+#STAGE_TABLE+' where '+ #CUR_SOURCE_COLUMN +' IS NULL'
PRINT #SQL1
INSERT INTO #TEMP_TABLE
exec (#SQL1)
END
IF (LTRIM(RTRIM(#CUR_DATA_CHECK)) = 'D')
BEGIN
-- SET #SQL1 = 'SELECT ''aaa'' as column1, ERP_PO_DOCNUMBER as column2
-- from PURCHASE_ORDER_STAGE where '+ #CUR_SOURCE_COLUMN +' IS NULL'
SET #SQL1 = 'SELECT ERP_PO_ID, '''+#CUR_ERROR_PROPERTY2+''' as column1,'+#SOUCOL+'''|1| ERR_01 '''''+#CUR_ERROR_VALUE2+'''+'' in the input Worksheet'' as column2
from [ERP_ADMIN].'+#STAGE_TABLE+' where isdate('+ #CUR_SOURCE_COLUMN +') =0'
PRINT #SQL1
INSERT INTO #TEMP_TABLE
exec (#SQL1)
END
IF (LTRIM(RTRIM(#CUR_DATA_CHECK)) = 'N')
BEGIN
PRINT #CUR_SOURCE_COLUMN
SET #SQL1 = 'SELECT ERP_PO_ID, '''+#CUR_ERROR_PROPERTY2+''' as column1,'+#SOUCOL+'''|1| ERR_01 '''''+#CUR_ERROR_VALUE2+'''+'' in the input Worksheet'' as column2
from [ERP_ADMIN].'+#STAGE_TABLE+' where isnumeric('+ #CUR_SOURCE_COLUMN +') =0'
PRINT #SQL1
INSERT INTO #TEMP_TABLE
exec (#SQL1)
END
END
CLOSE stage_cursor
DEALLOCATE stage_cursor
SET #SQL1 = ''
SET #SQL1 = 'UPDATE PO_STAGE set PO_STAGE.ISVALID = ''N'' FROM ERP_ADMIN.'+#STAGE_TABLE+' PO_STAGE, #TEMP_TABLE TMP where PO_STAGE.ERP_PO_ID = TMP.ERP_POID'
PRINT #SQL1
exec (#SQL1)
/** DECLARE update_stage_cursor CURSOR LOCAL FOR
SELECT ERP_POID FROM #TEMP_TABLE
DECLARE #CURPOID [nvarchar](50)
OPEN update_stage_cursor
WHILE (0 = 0)
--begin of while
BEGIN
FETCH NEXT FROM update_stage_cursor INTO
#CURPOID
IF (##FETCH_STATUS = -1)
BREAK
END
CLOSE update_stage_cursor
DEALLOCATE update_stage_cursor **/
-- SELECT A.ERP_PO_ID FROM ERP_ADMIN.PURCHASE_ORDER_STAGE A, #TEMP_TABLE B where ERP_PO_ID = B.ERP_POID
SELECT ERRORCD, ERRORMSG FROM #TEMP_TABLE
END
GO
You should pass #TEMP_TABLE as parameter. To pass Table parameter you should create table type at first:
IF NOT EXISTS (SELECT 1 FROM sys.types WHERE NAME = 'TEMP_TABLE_TYPE')
CREATE TYPE TEMP_TABLE_TYPE AS TABLE(
ERP_POID nvarchar(50),
ERRORCD nvarchar(50),
ERRORMSG nvarchar(120)
);
And use it:
exec sp_executesql #Sql, N'#TEMP_TABLE TEMP_TABLE_TYPE readonly', #TEMP_TABLE
For epxplonation you can use this link Passing table variable into dynamic sql.
If you find this way not obvious, I advise to use temporary table instead of table varible:
CREATE TABLE #TEMP_TABLE (
ERP_POID nvarchar(50),
ERRORCD nvarchar(50),
ERRORMSG nvarchar(120)
);
On SQL Agent job I'm downloading data from main table (X). If the status equal 'WW' or 'WXY' I just want to all records insert into another table (Y) where I have created a trigger. Could you give me advise what should I change in my trigger definition? I receive error message when I try insert multiple records to DB2.Y table (agent job failed)
First code (downloading new data)
DECLARE #STARTTIME datetime
DECLARE #TIME datetime
DECLARE #ENDTIME datetime
SET #TIME=(SELECT MAX(Time) FROM DB2.Y)
SET #STARTTIME=(select dateadd(hour,1,getdate()))
SET #ENDTIME=(SELECT MAX(TIME) FROM DB1.X where TIME is not null)
IF #TIME = #ENDTIME
BEGIN
TRUNCATE TABLE DB2.Y;
INSERT INTO DB2.Y (Time) Values (#TIME)
END
ELSE
BEGIN
TRUNCATE TABLE DB2.Y
INSERT INTO DB2.Y ([Serv],[Status])
SELECT [SERV],[STATUS] FROM DB1.X WHERE TIME > #TIME and [SERV]='Description' and ([STATUS]='WW' or [STATUS]='WXY') ;
UPDATE DB2.Y
SET [Time]= #ENDTIME
END
The trigger code:
USE DB2
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TRIGGER [dbo].[TriggerName] ON Y
AFTER INSERT AS
DECLARE #SERV varchar(40)
DECLARE #STATUS varchar(3)
SET #SERV=(SELECT [SERV] FROM inserted)
SET #STATUS=(SELECT [STATUS] FROM inserted)
IF #STATUS in ('WW', 'WXY')
BEGIN
DECLARE #MSG varchar(500)
SET #MSG = 'Job "' + #SERV + '" failed!!!'
EXEC msdb.dbo.sp_send_dbmail #recipients=N'myemail#domain.com', #body= #MSG, #subject = #MSG, #profile_name = 'profilename'
END
INSERTED can contain multiple rows for multi-row INSERTs - it runs once per operation, not once per row.
Try a trigger like this instead:
USE DB2
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TRIGGER [dbo].[TriggerName] ON Y
AFTER INSERT AS
DECLARE #SERV varchar(40)
DECLARE #STATUS varchar(3)
IF EXISTS(SELECT [Status] FROM Inserted WHERE [STATUS] in ('WW', 'WXY'))
BEGIN
DECLARE #MSG varchar(8000)
INSERT INTO JobLog(Serv, Status)
SELECT Serv, Status FROM Inserted WHERE [STATUS] in ('WW', 'WXY')
SET #MSG = CAST(##ROWCOUNT as nvarchar) + 'Job(s) failed - see log for details'
EXEC msdb.dbo.sp_send_dbmail #recipients=N'myemail#domain.com', #body= #MSG, #subject = #MSG, #profile_name = 'profilename'
END
SELECT
Try something like this...
CREATE TRIGGER [dbo].[TriggerName] ON Y
AFTER INSERT
AS
BEGIN
SET NOCOUNT ON;
DECLARE #SERV varchar(40),#STATUS varchar(3), #MSG varchar(500)
Select [SERV], [STATUS] INTO #Temp
FROM inserted
Where [STATUS] IN ('WW', 'WXY')
Declare Cur CURSOR FOR
SELECT [SERV], [STATUS] FROM #Temp
OPEN Cur
FETCH NEXT FROM Cur INTO #SERV, #STATUS
WHILE ##FETCH_STATUS = 0
BEGIN
SET #MSG = 'Job "' + #SERV + '" failed!!!'
EXEC msdb.dbo.sp_send_dbmail #recipients=N'myemail#domain.com'
, #body= #MSG
, #subject = #MSG
, #profile_name = 'profilename'
FETCH NEXT FROM Cur INTO #SERV, #STATUS
END
CLOSE Cur
DEALLOCATE Cur
END
You could use a cursor to resolve your error. The cursor below iterates over all inserted records with a STATUS of either WW or WXY and sends out an email for each of them.
DECLARE error_cursor CURSOR FOR
SELECT [SERV],[STATUS] FROM inserted
WHERE [STATUS] in ('WW', 'WXY')
OPEN error_cursor
FETCH NEXT FROM error_cursor
INTO #SERV, #STATUS
WHILE ##FETCH_STATUS = 0
BEGIN
DECLARE MSG varchar(500)
SET #MSG = 'Job "' + #SERV + '" failed!!!'
EXEC msdb.dbo.sp_send_dbmail #recipients=N'myemail#domain.com', #body= #MSG, #subject = #MSG, #profile_name = 'profilename'
FETCH NEXT FROM vendor_cursor
INTO #SERV, #STATUS
END
CLOSE error_cursor;
DEALLOCATE error_cursor;
I created a table named Customers with the following columns:
ID
Name
Birthdate
Email
Manager
Entries
Name Birthdate Email Manager
---- ---------- -------------- -------
Jan 1986-05-15 jan#gmail.com None
Koos 1986-07-24 Koos#gmail.com 1
Sam 1991-07-24 Sam#gmail.com 1
Meaning that Koos and Sam's manager is Jan.
Now what I want to do is to determine if someone has a birthday today.
Create PROCEDURE [dbo].[EmailData]
AS
SET NOCOUNT ON
BEGIN
Declare #Date date
SELECT GETDATE(), Month(GetDate()), Day(GetDate()), Year(GetDate())
select
a.ID, a.Name,
a.BirthDate as EmpBirthday,
b.Name as Manager,
b.Email as ManEmail
from dbo.Customers a
inner join dbo.Customers b
on a.Manager = b.ID
where Month(a.BirthDate) = Month(GetDate())
and Day(a.BirthDate) = Day(GetDate())
END
Go
The above works fine, I get the results I want 100%.
What I want to do now is send the email of each employee whose birthday it is today to the employee's manager.
I came up with this but it does not seem to work and I have no idea why:
Create PROCEDURE EmailData
AS
BEGIN
Declare #email nvarchar(128)
Declare #Date date
SELECT GETDATE(), Month(GetDate()), Day(GetDate()), Year(GetDate())
DECLARE rcpt_cursor CURSOR FOR
select
b.Email
from dbo.Customers a
inner join dbo.Customers b
on a.Manager = b.ID
where Month(a.BirthDate) = Month(GetDate())
and Day(a.BirthDate) = Day(GetDate())
OPEN rcpt_cursor
FETCH NEXT FROM rcpt_cursor INTO #email
DECLARE #ServerAddr nvarchar(128)
Set #ServerAddr = 'smtp.gmail.com'
DECLARE #From nvarchar(128)
Set #From = 'My Email Address'
DECLARE #Bodytext nvarchar(512)
Set #BodyText = 'Your Employees have a birthday today.'
DECLARE #User nvarchar(128)
Set #User = 'My Email Address'
DECLARE #Password nvarchar(128)
Set #Password = 'My Password'
DECLARE #SSL int
Set #SSL = 0
DECLARE #Port int
Set #Port = 587
WHILE ##FETCH_STATUS = 0
BEGIN
PRINT #email
DECLARE #subject nvarchar(255)
SELECT #Subject = 'Happy Birthday' + #email
EXEC EmailData #ServerAddr,
#from, #email, #subject, #BodyText, #User, #Password, #SSL, #Port
FETCH NEXT FROM rcpt_cursor
INTO #email
END
CLOSE rcpt_cursor
DEALLOCATE rcpt_cursor
End
Go
Any help will be appreciated.
Ok I cracked it
First of all I set up a Database mail account
Then I wrote a procedure
USE [Customers]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[usp_SendEmail]
AS
Declare #email nvarchar(128)
Declare #name nvarchar(128)
Declare #Date date
SELECT GETDATE(), Month(GetDate()), Day(GetDate()), Year(GetDate())
DECLARE rcpt_cursor CURSOR FOR
select
a.Name,
b.Email
from dbo.Customers a
inner join dbo.Customers b
on a.Manager = b.ID
where Month(a.BirthDate) = Month(GetDate())
and Day(a.BirthDate) = Day(GetDate())
OPEN rcpt_cursor
FETCH NEXT FROM rcpt_cursor
INTO #name,#email
WHILE ##FETCH_STATUS = 0
BEGIN
PRINT #email
Declare #subject nvarchar(255)
Declare #Bodytext nvarchar(512)
Set #BodyText = #Name + '' + ' has a birthday today. Please congrad him'
Set #Subject = 'Employee Birthday'
exec msdb.dbo.sp_send_dbmail
#Profile_Name = 'HappyBirthday',
#Recipients = #email,
#Body = #BodyText,
#Subject = #Subject
FETCH NEXT FROM rcpt_cursor
INTO #name,#email
END
CLOSE rcpt_cursor
DEALLOCATE rcpt_cursor
Go
Exec [usp_SendEmail]
The procedure now run through the hole customer table check if there are birthday dates that much and send the email to the managers whose employees have a birthday.