I created a trigger on a table, and now I can't alter or delete it.
I cant even access the table.
what can I do?
trigger script:
create trigger [Products].[InsertLessThen5InStock]
on [Products].[Products]
after update
as
BEGIN
DECLARE #ck int
select UnitsInStock from Products.Products where UnitsInStock<5
set #ck=##ROWCOUNT
print #ck
if #ck >0
BEGIN
DECLARE #mails varchar (200)
exec dbo.Manager_email #mails output
EXEC msdb.dbo.sp_send_dbmail
#profile_name = 'DefaultMailSender',
#recipients = #mails ,
#body = 'Products that will expire in less then 5 days',
#subject = 'Products that will expire in less then 5 days',
#body_format = 'HTML',
#query = 'EXECUTE MadCat.dbo.SaveTableAsHTML
#DBFetch =''select UnitsInStock from Products.Products where UnitsInStock<5'''
END
END
GO
Since it is complaining about not being able to get a lock, it means some process has reserved the table exclusively. You should try restarting the server, and then issuing the drop trigger command.
drop trigger [Products].[InsertLessThen5InStock]
Related
One of my customer's website had been getting injection attack (inserting ads in emails) and at that time I didn't know how to handle the attack so I set trigger on update and delete to send me an email so I would know ads were added to table. However, I did not receive any email when values got changed.
ALTER TRIGGER [dbo].[TRIG_DEL]
ON [dbo].[A]
INSTEAD OF DELETE
AS
BEGIN
DECLARE #str VARCHAR(100)
SET #str = CONCAT('Someone is trying to delete A table at ', CURRENT_TIMESTAMP)
EXEC [msdb].[dbo].sp_send_dbmail
#profile_name = 'A_Email',
#recipients = 'abc#def.com;',
#subject = 'UPDATE ALERT',
#body = #str
END
This is my trigger and it works fine when I test it. Is there any way to avoid trigger? I just want to know how the attacker avoided the trigger, out of curiosity.
I've only started exploring with triggers recently. I've set up my database mail function and all is working well. My trigger works perfectly if the column value is changed, but how do I get the value/row that changed?
USE [database]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER TRIGGER [dbo].[triggerName] ON [dbo].[tableName]
FOR UPDATE
AS
declare #cust varchar(100);
if update(Column)
BEGIN
SET NOCOUNT ON
set #cust = THE VALUE MUST GO HERE I ASSUME
END
EXEC msdb.dbo.sp_send_dbmail
#recipients = 'someone#example.com',
#profile_name = 'ProfileName',
#subject = 'Customer Information Changed',
#body = #cust;
Compare the values in inserted and deleted. If they are not the same, then the value changed.
I am trying to create a trigger which should shoot a mail as soon a record is added to a said table. For this purpose I have created a the following trigger, which is sort of catering my requirement:
ALTER TRIGGER [dbo].[EMAIL_ALERT_NEW]
ON [dbo].[APTCR_LOG]
after insert
as
BEGIN
SET NOCOUNT ON;
DECLARE #body NVARCHAR(MAX) = N'';
SELECT AUDTUSER, NAMERMIT ,AMTRMITTC,IDRMIT FROM APTCR_LOG inserted
SELECT #body += CHAR(13) +++ CHAR(10) +++ RTRIM(AUDTUSER) +++ RTRIM(NAMERMIT) +++RTRIM(AMTRMITTC) +RTRIM(IDRMIT) FROM APTCR_LOG inserted;
--SELECT NAMERMIT, AUDTUSER ,AMTRMITTC FROM APTCR_LOG WHERE AMTRMITTC > 100000
BEGIN
--SELECT AUDTUSER, NAMERMIT ,AMTRMITTC,IDRMIT FROM APTCR_LOG inserted WHERE AMTRMITTC > 100000.000
EXEC msdb.dbo.sp_send_dbmail
#recipients = 'ublaze#gmail.com',
#profile_name = 'default',
#subject = 'NEW PAYMENT',
#body = #body;
END
end
The issue is it's sending all the records on the table where I just need the last record which was added in to the table.
Can somebody please help with this situation?
I have made a trigger to run upon insert of record, which should first check the current time and if it is beyond a particular hour and minute, it should fire the trigger and should take data from a table and use those values in the subject and body of the email.
Below is the trigger which is working fine but i need to add time condition and I tried to query a table based on the record inserted into the table but I am not getting the desired email.
As you can see that I tried to use a table value to be sent in the subject but I get the email with SQL Server Message in the subject.
Another thing I want to add is to query the table and check if the INSERTED.USERID is available in the table or not, if it is not available, then no need to fire the trigger.
USE [Attendance]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER TRIGGER [dbo].[after_insert_ATT_LOG] ON [dbo].[ATT_LOG]
FOR INSERT
AS
BEGIN TRY
DECLARE #PositionCode NVARCHAR(5), #FullNameE NVARCHAR(45), #FullNameE2 NVARCHAR(40), #Email NVARCHAR(50), #EDescription NVARCHAR(100), #ReportingToShortNo NVARCHAR(5), #ReportingtoFullNameE NVARCHAR(45), #ReportingEmail NVARCHAR(50)
Select #PositionCode=ED.POsitionCode, #FullNameE=EP.FullNameE,#FullNameE2=ED.FullNameE, #Email=ED.Email, #EDescription=EP.EDescription, #ReportingToShortNo=EP.ReportingToShortNo, #ReportingtoFullNameE=EP.ReportingtoFullNameE, #ReportingEmail=(Select Email
FROM HRSystem.dbo.employeedetails WHERE PositionCode= EP.ReportingToShortNo) FROM HRSystem.dbo.employeedetails ED, HRSystem.dbo.Position EP WHERE ED.PositionID = EP.PositionID AND ED.PositionCode = (Select INSERTED.USERID FROM INSERTED) COLLATE DATABASE_DEFAULT;
EXEC msdb.dbo.sp_send_dbmail
#recipients = 'abc#abc.com',
#profile_name = 'Alert',
#subject = #FullNameE,
#body = 'Test Alert';
END TRY
BEGIN CATCH
DECLARE #dummy int
SET #dummy = 1
END CATCH
as for your second concern
Another thing I want to add is to query the table and check if the INSERTED.USERID is available in the table or not, if it is not available, then no need to fire the trigger.
a FOR INSERT trigger fires right after a row is inserted. meaning, the USERID you wanna look for is sure to be in table ATT_LOG.
and as for your first issue. please try the t-sql code below:
CREATE TRIGGER [dbo].[after_insert_ATT_LOG] ON [dbo].[ATT_LOG]
FOR INSERT
AS
BEGIN TRY
DECLARE #PositionCode NVARCHAR(5), #FullNameE NVARCHAR(45), #FullNameE2 NVARCHAR(40), #Email NVARCHAR(50), #EDescription NVARCHAR(100), #ReportingToShortNo NVARCHAR(5), #ReportingtoFullNameE NVARCHAR(45), #ReportingEmail NVARCHAR(50)
Select #PositionCode=ED.POsitionCode, #FullNameE=EP.FullNameE,#FullNameE2=ED.FullNameE
, #Email=ED.Email, #EDescription=EP.EDescription
, #ReportingToShortNo=EP.ReportingToShortNo
, #ReportingtoFullNameE=EP.ReportingtoFullNameE
, #ReportingEmail=
(Select Email
FROM HRSystem.dbo.employeedetails
WHERE PositionCode= EP.ReportingToShortNo)
FROM HRSystem.dbo.employeedetails ED, HRSystem.dbo.Position EP
WHERE ED.PositionID = EP.PositionID
AND ED.PositionCode =
(Select INSERTED.PositionCode FROM INSERTED) COLLATE DATABASE_DEFAULT;
EXEC msdb.dbo.sp_send_dbmail
#recipients = 'abc#abc.com',
#profile_name = 'Alert',
#subject = #FullNameE,
#body = 'Test Alert';
END TRY
BEGIN CATCH
DECLARE #dummy int
SET #dummy = 1
END CATCH
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.