Agent job that emails from custom email table - sql

I used to have triggers in my database that used cursors / sp_send_dbmail to email when certain columns were updated. I was told this was not best practice so I created a new table called EmailNotify that contains columns like recepient, subject, body etc. So instead the triggers now insert into this table the email I want to send.
I want to create a Job that runs every few minutes that checks this table and emails. The item below is what I came up with but is it okay to use cursors in this case? Should the table include a sent field so I know which rows I sent? Can I change that inside the cursor? Or would it be recommended to truncate the table afterwards?
DECLARE #emailSubject AS NVARCHAR(100);
DECLARE #emailRecipients AS NVARCHAR(100);
DECLARE #emailBody AS NVARCHAR(max);
DECLARE cur CURSOR LOCAL READ_ONLY FAST_FORWARD FOR
SELECT
recipients,
subject,
body
FROM
EmailNotify;
OPEN cur
FETCH NEXT FROM cur INTO
#emailRecipients,
#emailSubject,
#emailBody
WHILE ##FETCH_STATUS = 0
BEGIN
EXEC msdb.dbo.sp_send_dbmail
#profile_name = 'name',
#recipients = #emailRecipients,
#body = #emailBody,
#body_format = 'HTML',
#subject = #emailSubject;
FETCH NEXT FROM cur INTO
#emailRecipients,
#emailSubject,
#emailBody
END
CLOSE cur
DEALLOCATE cur

I would
Add an EmailSent(DATETIME) = NULL column to your table
Create an EmailSent variable at the top of your proc and set it to GETDATE()
UPDATE <YOURTABLE> SET EmailSent = #EmailSent WHERE EmailSent IS NULL
Add a WHERE EmailSent = #EmailSent to your query for the email
You can accomplish this with a SSRS report with a subscription or data-bound subscription instead of this job, but it's really just a matter of preference. Formatting is easier in SSRS, otherwise you're messing with dynamic HTML in your message body. Been there, not pleasant.

Related

I don't want to send empty email if no results found

I have used cursor to loop through my values and Every time i am sending a mail but if no result found then it was sending an empty mail,How can i avoid that?
This is very much guessed logic, but based on the very vague comments and question, I imagine you simply need to use an IF. This is Pseudo-SQL, however...
DECLARE #TableHTML varchar(MAX);
SELECT #TableHTML = {Your HTML data expression};
IF #TableHTML IS NOT NULL BEGIN
EXEC sp_send_dbmail #Subject = {Your Subject},
#Body = #TableHTML,
#....;
END

Loop for multiple database and user creation in SQL, assign user to the database

after creating login using windows authentication ,
need to assign user to the database
and provide permissions to that user.
Could anyone please help me with that.
Thanks in advance.
-- BULK INSERT tempNames.dbo.tempNames
-- FROM 'C:\Users\Videos\file.txt'
-- WITH
-- (
-- ROWTERMINATOR ='\n'--
-- )
USE [master]
GO
DECLARE #NameCursor as CURSOR;
DECLARE #NAME AS NVARCHAR(50);
DECLARE #NAME2 AS NVARCHAR(50);
DECLARE #NIUNT AS NVARCHAR(50);
SET #NIUNT ='niunt';
SET #NameCursor = CURSOR FOR
SELECT id
FROM test.dbo.Sheet1$
OPEN #NameCursor;
FETCH NEXT FROM #NameCursor INTO #Name;
WHILE ##FETCH_STATUS = 0
BEGIN
PRINT #Name
Creating database using #name
set #name2 ='create database '+#Name + ';'
exec (#name2)
BEGIN
SET NOCOUNT ON
DECLARE #SQL NVARCHAR(4000);
Creating login using #name
SET #SQL = 'CREATE LOGIN [' +#NIUNT +'\'+ #NAME + '] from windows';
exec(#SQL);
-END;
FETCH NEXT FROM #NameCursor INTO #Name;
END
GO
This is awfully intricate. It seems easier to operate directly upon the underlying system tables that actually represent the authentication and authorization data. Then you won't have to muck about with cursors and such.
FOR EXAMPLE, let's say that logins were represented by a table, SYS$LOGINS, with fields SYS$USERNAME and SYS$PASSWORD. Isn't it easier to just INSERT a record for user 'joe' into that table (let's not worry about the details of how encrypted passwords are stored: it's just a quick example!) than to have to define cursors, and construct SQL strings, and exec() them?
I should think you have to be the SYSTEM user to do all this, but I'm sure you already are.

sp_send_dbmail sending mail even if condition is false - SQL

I have an IF statement part of a stored procedure as follows :
BEGIN TRY
IF EXISTS (SELECT which I have confirmed returns no results, has a variable called from another table in the where clause)
BEGIN
EXEC msdb.dbo.sp_send_dbmail
#profile_name = #dynamic_profile,
#recipients = #dynamic_recipient,
#subject = #subjectline,
#body = #mailHTML,
#body_format = 'HTML';
END
END TRY
This is tied to a job that runs every 15mins.
Why is it keep sending me blank emails when the IF statement asks to skip the mail sending if the select returns no results?
My NOCOUNT is set to ON
Try - instead:
IF (SELECT COUNT(*) FROM whatever) > 0
BEGIN
--MAIL
END

Bulk Update Email Trigger

I created a update trigger in Microsoft SQL Server that would email me if a date changed in a row.
Similar to this:
IF UPDATE(ColumnName)
BEGIN
DECLARE #columnVal AS DATETIME
SELECT
#columnVal = i.columnName
FROM
inserted i JOIN deleted d on i.RowId= d.RowId;
EXEC msdb.dbo.sp_send_dbmail
#profile_name = 'me',
#recipients = 'me#company.com',
#body = 'blah blah datechange',
#body_format = 'HTML',
#subject = 'subject';
END
it worked fine for a time.
Then I switched over to batch updates and only the first row email is sent out if the date changes on multiple rows. I tried to set up a cursor to roll through the changes but I cannot get it to work, Similar to below:
DECLARE #columnVal AS DATETIME
DECLARE cur CURSOR LOCAL READ_ONLY FAST_FORWARD FOR
SELECT
i.ColumnName
FROM
inserted i JOIN deleted d on i.RowId= d.RowId;
OPEN cur
FETCH NEXT FROM cur INTO #columnVal
WHILE ##FETCH_STATUS = 0
BEGIN
IF UPDATE(ColumnName)
BEGIN
EXEC msdb.dbo.sp_send_dbmail
#profile_name = 'me',
#recipients = 'me#company.com',
#body = 'blah blah datechange',
#body_format = 'HTML',
#subject = 'subject';
END
FETCH NEXT FROM cur INTO #columnVal
END
CLOSE cur
DEALLOCATE cur
Any ideas on how to accomplish this task? Would the Update(ColumnName) function even work properly nested inside a cursor (would it actually tell me if that column was updated for that row?)
A cursor inside a trigger is a very very bad idea.
A trigger should be very lean - it shouldn't do a lot of work! I would recommend to only "take a note" of who you have to send an e-mail to - but leave the actual sending of the e-mail to a separate e.g. SQL Server Agent Job which is not part of the trigger.
Triggers are fired often and often unexpectedly - don't put a log of processing burden into them! And especially not a performance killer like a cursor!
To find those rows that you're interested in, you can use a WHERE clause something like:
WHERE inserted.ColumnName <> deleted.ColumnName
In the context of an UPDATE trigger, this means the new value of ColumnName is different from the old value --> this column has been updated.

Does anyone know why this code is sending users duplicate emails?

We have a stored procedure that is supposed to check db and select all records where sentFlag is No.
Once record(s) found, the stored proc invokes sp_send_dbmail with passed parameters and then sends an email to affected individuals.
This appears to work.
The issue we are having so far though is that each indivual is receiving duplicate emails.
Any ideas what part of this code could be causing this?
OPEN MAIL_CURSOR
FETCH MAIL_CURSOR into #mail1, #sender,#content1
WHILE ##FETCH_STATUS = 0
BEGIN
SELECT #email = #email+';'+Email
FROM GRVRIEVANCES
WHERE sentFlag = 'No'
EXEC msdb.dbo.sp_send_dbmail
#profile_name = 'Grievances',
#recipients = #email,
#subject = 'Account Details',
#body = #content1;
FETCH MAIL_CURSOR INTO #mail1, #sender, #content1
END
CLOSE MAIL_CURSOR
DEALLOCATE MAIL_CURSOR
END
If you set email to an initial value within the loop, does the issue go away? Also, make sure you setting the sentflag to 'yes'.
WHILE ##FETCH_STATUS = 0
BEGIN
SET #email=''
SELECT #email = #email+';'+Email
Back to basics to solve this one.
Start with some debugging:
Comment out your EXEC part
Add PRINT #email in the same spot
Run the cursor and see the reults, they should be quite enlightening!
Essentially what you're doing is on every cursor execution you are building up this big ol' string of email addresses for all GRVRIEVANCES WHERE sentFlag = 'No'.