Does anyone know why this wouldn't work? It's a trigger which checks the value of a field on insert and update and sends an email with the value of an id column from the offending row.
ALTER TRIGGER [dbo].[DB]
ON [dbo].[table]
AFTER INSERT, UPDATE AS
BEGIN
IF EXISTS(SELECT 1 FROM inserted WHERE value = 5)
BEGIN
EXEC msdb.dbo.sp_send_dbmail
#recipients = 'me#derp.com',
#profile_name = 'MailProfile',
#subject = 'DB.dbo.table trigger',
#body = '',
#execute_query_database = 'DB',
#query = 'USE DB SET NOCOUNT ON SELECT id FROM dbo.table WHERE value = 5';
END
END
The problem seems to be the #query in the sp_send_dbmail function. When I manually try triggering it I receive the following error;
No row was updated.
The data in row x was not committed.
Error Source: .Net SqlClient Data Provider.
Error Message: Timeout expired. The timeout period elapsed prior to completion of the operation or the server is not responding.
Correct the errors and retry or press ESC to cancel the change(s).
When I remove #execute_query_database and #query and add some plain text to the #body var the trigger works and I receive an email.
I've also tried changing the #query value to something really simple e.g. SELECT "Test" as test but this didn't help.
I'm completely new to triggers so if the problem is painfully obvious... apologies :)
You need semi-colons:
#query = 'USE DB; SET NOCOUNT ON; SELECT id FROM dbo.table WHERE value = 5;';
Related
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.
The trigger I am using is not firing, any ideas/help is appreciated. I checked the sysmail_allitems and its empty. To give some more explanation, I have a program where we submit travel requests through a form, when you submit a form a new row is created in TS_CUSTOM_TRVLBCK, everytime this happens I want an email to be sent with the conditions below. I have submitted a new form form (added image), the row is there but the trigger didnt fire.
My goal is to receive an email when one of the users in the where statement submits a request (a new row is created)
CREATE TRIGGER [dbo].[TS_TRAVEL_NEW_IIS]
ON [dbo].[TS_CUSTOM_TRVLBCK]
FOR INSERT
AS
BEGIN
SET NOCOUNT ON;
DECLARE #user Varchar(100)
DECLARE #subject Varchar(100)
DECLARE #body Varchar (200)
SELECT #user + RTRIM(TRVL_INITIATOR) FROM inserted;
SET #subject = 'New Travel Request - ' + #user
SET #body = 'Kindky note that user ' + #user + ' has submitted a new travel request.'
IF EXISTS (SELECT 1 FROM inserted WHERE [TRVL_INITIATOR] IN ('Luke Gatt','Marcelle Attard','Matthew Borg Dingli','Mark Schembri','Fiona Tesi','Charmaine Buttigieg','Stephen Mifsud','Tessabelle Cammilleri'))
BEGIN
EXEC msdb.dbo.sp_send_dbmail
#recipients = 'luke.gatt#mca.org.mt',
#profile_name = 'AbsenceMailer',
#subject = #subject,
#body = #body;
END
END
GO
If I make a change to MyTable on MyDatabase, I want it to delete the contents of TestTable on TestDatabase on MYLINKEDSERVER and reinsert everything from scratch. To do this, I use a trigger on MyTable. I know this is inefficient but the number of records is less than 10.
In case the linked server is down, I want it to still commit the changes locally to MyTable and just send an email alert stating that the linkedserver could not be updated. I am failing to get the local transaction to commit when the linkedserver is unavailable... I've tried messing with XACT_ABORT but I just get different errors.
What am I doing wrong?
CREATE TRIGGER trig_updatelinkedserver ON MyDatabase.dbo.MyTable
FOR INSERT, UPDATE, DELETE
AS
BEGIN
DECLARE #linked_server SYSNAME = 'MYLINKEDSERVER'
, #tablename SYSNAME --name of the table calling the trigger so we can send error details in alert eamil
SELECT #tablename = OBJECT_NAME(parent_object_id)
FROM sys.objects
WHERE sys.objects.name = OBJECT_NAME(##PROCID)
BEGIN TRY
--If linkedserver fails to connect, we do not want the remaining code in the block to run
--but we do want the original transaction that triggered this to complete.
EXEC sp_testlinkedserver #servername = #linked_server
DELETE FROM MYLINKEDSERVER.TestDatabase.dbo.TestTable
INSERT INTO MYLINKEDSERVER.TestDatabase.dbo.TestTable
SELECT *
FROM MyDatabase.dbo.MyTable
END TRY
BEGIN CATCH
DECLARE #subj VARCHAR(1000) = 'TRIGGER FAILURE: ' + #tablename + ': Could not locate linkedserver ' + #linked_server
EXEC msdb.dbo.sp_send_dbmail
#recipients = 'foo#bar.com'
, #subject = #subj
, #body = ''
, #body_format = 'HTML'
, #profile_name = 'MyEmailProfile'
END CATCH
END
Error handling in tsql is complicated and inconsistent. What are you doing wrong? Making assumptions. Here is what Erland says in his lengthy discussion about the topic:
What is important to understand about triggers is that they are part of the command that fired the trigger, and in a trigger you are always in a transaction, even if you did not use BEGIN TRANSACTION. Sometimes I see people in SQL Server forums ask if they can write a trigger that does not roll back the command that fired the trigger if the trigger fails. The answer is that there is no way that you can do this reliably, so you better not even try. If you have this type of requirement, you should probably not use a trigger at all, but use some other solution.
So take that last sentence to heart. Note that the link takes you into the middle of the discussion. And there are links at the end of the page that continue to related topics - one of which is about linked servers.
I've created a trigger on a table that send an email, however it sends the query as text as opposed to the actual results of the query.
Hopefully someone can tell me where I'm going wrong. Trigger is:
[dbo].[EventMail] ON [dbo].[Table1] AFTER INSERT AS
BEGIN
SET NOCOUNT ON;
IF EXISTS (SELECT * FROM inserted WHERE Column1 LIKE '%Test%')
BEGIN
DECLARE #msg nvarchar(max)
SET #msg = 'SELECT * FROM Inserted Where Column1 Like ''%Test%'''
--// CHANGE THE VALUE FOR #recipients
EXEC msdb.dbo.sp_send_dbmail
#recipients=N'email#email.co.uk',
#body= #msg,
#subject = 'Worksheet Error',
#profile_name = 'profilename'
END
END
Your query is in quotes. Take out the single quotes and it will set #msg to the results of that query.
A warning though. It will fail if that query returns more than one result. You should also declare the column.
I am stuck in a problem. There is an application that adds data to database, which is a closed source.
I am creating its web interface. The functionality I want is, that, if a value of some Field in a column is greater than a value in another field in a column, SQL server should http post a message to my site.
Is it possible in Microsoft SQL?
and if yes, How?
Ok, if another software is doing the inserts, you could do it like this...
ALTER TRIGGER [dbo].[ABCD] ON [dbo].[XXX]
FOR INSERT
AS
Declare #A -- from column 1 in INSERT
Declare #B -- from column 2 in INSERT
if (#A > #b)
begin
EXEC msdb.dbo.sp_send_dbmail
#recipients = #email,
#body = #message,
#subject = 'Latest record has column value A greater than column value B'
end
else
begin
--do whatever
end
Ps. sp_send_dbmail is a stored procedure that sends email or messages