I am trying to write a SQL trigger for the first time but running into a problem.
I have a database called mytest and within that is a table called customer. When someone registers a customer record is created. On the signup form that creates the customer record there is an option to add a doctors name.
What I am trying to do within the trigger is send the doctor an email with a simple message "This customer says you are their doctor, please can you reply to this email stating yes or No". My main option is to automate this part of the procedure to update the SQL table once I get this part working!
Here is what I have written so far
CREATE TRIGGER dbo.SEND_MAIL_TO_PRACTITIONER
ON dbo.mytest
AFTER INSERT
AS
BEGIN
DECLARE #PractitionerName VARCHAR(100)
DECLARE #body VARCHAR(100)
SET #PractitionerName=(SELECT PractitionerName FROM customer )
SET #body=(SELECT customername FROM customer)+' emailed us saying you were his doctor, please can you confirm yes or no'
IF #PractitionerName IS NOT NULL
BEGIN
EXEC msdb.dbo.sp_send_dbmail
#recipients = #PractitionerName,
#subject = 'TEST',
#body = #body;
END
END
GO
The SQL executes but no emails are being sent. I'd also like to change customername to a combination of FirstName and LastName fields.
Anybody help point me in the right direction?
You need to start the mail service first in SQL server consider sending a test mail.. If it fails check the mail log by right click in db mail option!
Configure as the doc
http://msdn.microsoft.com/en-IN/library/ms190307.aspx
http://technet.microsoft.com/en-us/library/ms176087.aspx
Related
I have below EmployeeData table and due to some known reasons BAD data is getting inserted and i am working on code fix, but meanwhile i want to check for bad data until the fix is deployed. If you observe John has 1 for both Active and IsEmpTermed columns.
Currently i am running the below query to check for Bad data manually in SQL Server. I want to automate this task and send an email to me if it finds bad data i.e. Active =1 and IsEmpTermed =1. What and How to do it?
select * from EmployeeData Where Active=1 and IsEmpTermed = 1;
Thanks in advance.
Quick way would be use the #query argument with sp_send_dbmail and put that code in a SQL Server Agent Job.
Here's a simple example of what that sp_send_dbmail looks like:
EXEC msdb.dbo.sp_send_dbmail
#profile_name = '' --This is specific to your setup
,#recipients = 'your#email.com'
,#subject = 'This is the subject'
,#query = 'select EmpID, FirstName, LastName from EmployeeData Where Active=1 and IsEmpTermed = 1' --The query
,#execute_query_database = '' --The name of your database goes here where the query should be executed
That will basically execute the query you specified in #query, dump the results into an email and send it to whomever is in #recipients
If you don't know what the #profile_name is for your server configuration you can run
EXEC msdb.dbo.sysmail_help_profileaccount_sp;
That will return a list of the mail profiles configured on your server. You will use the value from the "profile_name" column. If there are multiples, this is something I can't tell you as it is specific to your server configuration.
Once you have all that defined and working by manually running it in SSMS, go create a SQL Server Agent Job with a T-SQL step and add the "EXEC msdb.dbo.sp_send_dbmail" code. Defined a schedule at whatever frequency you would like it to run.
A lot of times I'll code it to check if the data issue exists before sending an email, so it will only send an email when the data issue exists so it won't keep spamming me if there are no issues, something like this
--The IF EXISTS checks if the data issue exists before sending an email
IF EXISTS(SELECT TOP 1 'x' FROM dbname.dbo.EmployeeData Where Active=1 and IsEmpTermed = 1)
BEGIN
EXEC msdb.dbo.sp_send_dbmail
#profile_name = '' --This is specifc to your setup
,#recipients = 'your#email.com'
,#subject = 'This is the subject'
,#query = 'select EmpID, FirstName, LastName from EmployeeData Where Active=1 and IsEmpTermed = 1' --The query
,#execute_query_database = '' --The name of your database goes here
END
I'm looking for a way to send emails (or reminders/confirmations) to users who create a new record in a web application, which is then inserted into a table. Basically a dynamic way of sending emails.
I've been reading online about Triggers and DB mail and there seems to be alot of disadvantages going with this approach.
Does anyone have any recommendations on the best way to achieve this?
Flow: New Record Inserted into DB Table ->>> At this point the email address of the user who created the record in the application should receive a mail (basically a confirmation mail).
What I've tried already:
DB mail is already configured and working.
I've made the below Trigger (very basic) but from reading online using a trigger in this way will lead to load/performance issues of my DB.
But I'm on unsure on how to generate the emails and last record inserted.
CREATE TRIGGER [dbo].[INSERT_Trigger] ON [dbo].[Entity]
FOR INSERT
AS
EXEC msdb.dbo.sp_send_dbmail
#profile_name = 'DBMail',
#recipients = 'admni#domain.com', ####Here I would need dyncamic emails based on what user enters the new record which are stored in the same table
#query = 'Select Description From Entity where 'Last inserted record'####Here I would need the last record for that user entered
#subject = 'Subject' ,
#Body = 'Message Body',
#importance = 'High',
IMHO this approach is a design flaw: the DB tier is something that should be one of the leaves of the tier tree. The fact that the MS SQL Server is actually an application server and has support for such things is a legacy, but I don't think that it should be used.
At first look:
you might need to switch to another RDBMS
your production environment might not support SMTP for any reason
your attempt to send the mail could fail for various reasons - resulting in user not being notified and never trying it again
Yes, indeed, you can use SQL Server even as a message bus but would not be an efficient one. This concept is actually dispatching events of "notification needed" kind. The event is implemented as insert and the trigger is the consumer. But the event is produced inside your application, in a higher tier. Why not reacting to it there? Or, use the database only as a queue: store the details there, but process them in a way where you have more control.
You have not told us about the application you are creating, but I would create a separate background task (the implementation could vary depending on the application design - can be an OS-level scheduled task, windows service, or a background worker in your application) that checks periodically for mails not yet sent, and tries to send them, storing the result in the record. Things might get of course more complicated depending on load. But this way you can retry, and you are certainly taking load of the DB server, but at least you have the possibility to do so.
I have a trigger that works as u asked
First insert records in temporary table from inserted table
Second, declare parameters that you need
Third, add a cursor in your trigger and get parameters that u need in cursor from temporary table
Inside trigger you can declare recipients as u needed to be, query, and other stuffs
CREATE TRIGGER Trigger ON [Entity]
FOR INSERT
not for replication
AS
select ins.* into #temp from inserted ins
declare #Param1 integer, #Param2 integer
declare cursor forward only for
select Col1, Col2 from #temp order by Col1
open cursor
fetch next from cursor into #Param1, #Param2
while ##fetch status = 0
begin
declare #recipients varchar (max), #query varchar(max)
select #recipient = Col1 -- or whatever col contains the recipient address
from #temp
where Col1 = #Param1
select #query = description
from #temp
where Col2 = #Param2 -- or whatever condition give u the description for parameter
exec sp_send_dbmail
#profile_name = 'profile',
#recipients = #recipient
#subject = 'Subject' ,
#Body = #query,
#importance = 'High'
fetch next from cursor into #Param1, #Param2
end
close cursor
deallocate cursor
drop table #temp
--- note that the body can be formatted in html format, like bellow
declare #body varchar(max)
select #body = '<html><body>'
select #body = #body+'Hello'+'<b><b>'
select #body = #body+'Here is the description:'+#query+'<b><b>'
select #body = #body+'Regards'
select #body = #body+'</body></html>'
i have a table in SQl server which occasionally gets data from a linked server, and than i have to do activities on it .
but the problem is there is no way to check if the data is inserted in table (table is always truncated after performing the activity so next time when data is pushed table is already empty) i manually check daily for data if it is inserted or not .
what i want is to get auto alert on my email (i already have db_mail configured and working) whenever the data is pushed in a table .
i have sa admin and complete privileges on Database and also on Windows server 2012 R2
You can do this with a trigger but you will have to do some preparations with privileges so the executor (the login that's inserting the records on your tracking table) can send email correctly:
CREATE TRIGGER dbo.TrackingTableNameAfterInsert ON TrackingTable
AFTER INSERT
AS
BEGIN
EXEC msdb.dbo.sp_send_dbmail
#profile_name = 'YourConfiguredProfile',
#recipients = 'youremail#mail.com',
#subject = 'Records were inserted on TrackingTable',
#body = ''
END
You might want to encapsulate the email sending on an SP and configure it's permissions there.
In regards to the following:
...table is always truncated after performing the activity so next time
when data is pushed table is already empty...
You can create a historical table and use a trigger to also insert inserted records on this table, so the TRUNCATE or DROP of the original one won't affect the copied records.
CREATE TABLE TrackingTableMirror (
/*Same columns and types*/
InsertedDate DATETIME DEFAULT GETDATE())
GO
CREATE TRIGGER dbo.TrackingTableInsertMirror ON TrackingTable
AFTER INSERT
AS
BEGIN
INSERT INTO TrackingTableMirror (
/*Column list*/)
SELECT
/*Column list*/
FROM
inserted AS I
END
This way you can check all records on this mirrored table and not the volatile one (and avoid all the email sending).
1) Create Profile and Account
You need to create a profile and account using the Configure Database Mail Wizard which can be accessed from the Configure Database Mail context menu of the Database Mail node in Management Node. This wizard is used to manage accounts, profiles, and Database Mail global settings.
2) Run Query
sp_CONFIGURE 'show advanced', 1
GO
RECONFIGURE
GO
sp_CONFIGURE 'Database Mail XPs', 1
GO
RECONFIGURE
GO
3)
USE msdb
GO
EXEC sp_send_dbmail #profile_name='yourprofilename',
#recipients='test#Example.com',
#subject='Test message',
#body='This is the body of the test message.
Congrates Database Mail Received By you Successfully.'
through the table
DECLARE #email_id NVARCHAR(450), #id BIGINT, #max_id BIGINT, #query NVARCHAR(1000)
SELECT #id=MIN(id), #max_id=MAX(id) FROM [email_adresses]
WHILE #id<=#max_id
BEGIN
SELECT #email_id=email_id
FROM [email_adresses]
set #query='sp_send_dbmail #profile_name=''yourprofilename'',
#recipients='''+#email_id+''',
#subject=''Test message'',
#body=''This is the body of the test message.
Congrates Database Mail Received By you Successfully.'''
EXEC #query
SELECT #id=MIN(id) FROM [email_adresses] where id>#id
END
4) Trigger Code
CREATE TRIGGER [dbo].[Customer_INSERT_Notification]
ON [dbo].[Customers]
AFTER INSERT
AS
BEGIN
SET NOCOUNT ON;
DECLARE #CustomerId INT
SELECT #CustomerId = INSERTED.CustomerId
FROM INSERTED
declare #body varchar(500) = 'Customer with ID: ' + CAST(#CustomerId AS VARCHAR(5)) + ' inserted.'
EXEC msdb.dbo.sp_send_dbmail
#profile_name = 'Email_Profile'
,#recipients = 'recipient#gmail.com'
,#subject = 'New Customer Record'
,#body = #body
,#importance ='HIGH'
END
I refer this link.
I have several (12) stored procedures that are programmed as steps in a job that runs every night. Each stored procedure sends the results of a query to a few recipients. There are actually 4 procedures- each one associated with one of three databases and a different set of recipients to make 12 total. One of the recipient's email address became invalid. When that occurred, one (but only one!) of the four procedures began generating duplicate emails.
I understand from Stored procedure using SP_SEND_DBMAIL sending duplicate emails to all recipients that an invalid email address can initiate retry attempts. So, I've removed the offending address and also reduced the number of Account Retry to 0 on the DBMail Config. But the emails are still generated. They are sent to the invalid email address that has been removed as well as the other recipients.
If I run the job manually, the duplicates are not generated. I have tried deleting and re-creating the job, but the issue persists. I have changed the schedule of the job to send at another time- the duplicate emails are sent at the same time as the original schedule even though it has been deleted. Looking at the job/mail history, the offending emails do NOT appear.
Is this some sort of bug? The SQL of the procedure is shown below for reference:
DECLARE #qry varchar(2000)
SET #qry = 'SELECT Fields FROM TABLE WHERE Conditions'
SET NOCOUNT ON
EXEC msdb.dbo.sp_send_dbmail
#profile_name = 'Example Email',
#from_address = 'email#email.com',
#recipients = 'example1#email.com; example2#email.com',
#subject = 'SubjectLine',
#body = 'BodyText',
#query = #qry;
I get a form filled from the user through browser..
I enter the values in a database
I want to call a script on the entry made in the database
(Do not want to call it from browser as browser has timeout issues. This script can take 10 hrs if it needs to)
Looks like you need a trigger:
A trigger is a special kind of stored procedure that automatically executes when an event occurs in the database server.
Example:
USE AdventureWorks2012;
GO
IF OBJECT_ID ('Sales.reminder2','TR') IS NOT NULL
DROP TRIGGER Sales.reminder2;
GO
CREATE TRIGGER reminder2
ON Sales.Customer
AFTER INSERT, UPDATE, DELETE
AS
EXEC msdb.dbo.sp_send_dbmail
#profile_name = 'AdventureWorks2012 Administrator',
#recipients = 'danw#Adventure-Works.com',
#body = 'Don''t forget to print a report for the sales force.',
#subject = 'Reminder';
GO
CREATE TRIGGER (Transact-SQL)