How did my trigger get deleted? - sql-server

If you can figure out this one you are a true SQL guru! It's one of the weirdest things I've ever seen.
I've added a trigger to a table in our database. The server is SQL 2008. The trigger doesn't do anything particularly tricky. Just changes a LastUpdated field in the table when certain fields are changed. It's a "After Update" trigger.
There is a large C++ legacy app that runs all kind of huge queries against this database. Somehow (I've got absolutely no idea how) it is deleting this trigger. It doesn't delete any other triggers and I'm certain that it's not explicitly dropping the trigger or table. The developers of this app don't even know anything about my triggers.
How is this possible??
I've tried running a trace using SQL Server Profiler and I've gone through each command that it's sending and run them using SQL Management Studio but my trigger is not affected. It only seems to happen when I run the app. WTF :(
UPDATE:
Sorry I don't want to waste your time. I just realised that if I change the name of the trigger then it doesn't get deleted. Furthermore if I modify the trigger so it doesn't do anything at all then it still gets deleted. From this I can only guess that the other devs are explicitly deleting it but I've searched the trace for the trigger name and it's not there. I'll hassle them and see what they say. Thanks for the suggestions.
UPDATE 2:
The other devs reckon that they are not deleting it explicitly. It doesn't exist in sys.objects or sys.triggers so it's not a glitch with SSMS. So confused :( Guess I'll just rename it and hope for the best? Can't think of anything else to try. A few comments below have asked if the trigger is being deleted or just disabled or not working. As I stated, it's being deleted completely. Also, the problem is not related to the actual contents of the trigger. As I stated, it I remove the contents and replace with some extremely simple code that doesn't do anything then it is still deleted.
Cheers
Mark

Thoughts:
To delete a trigger requires ALTER permission = shouldn't be used by an app
Triggers can be disabled with ALTER TABLE
Triggers can be confused by testing for ##ROWCOUNT at the beginning to trap dummy updates etc
Is the trigger coded for single rows only and appears not to run
Does the trigger exists in sys.objects/sys.triggers: don't rely on Object Explorer in SSMS
A trigger can be deleted if the table is dropped and re-created
A trigger won't fire for TRUNCATE TABLE

I had an identical issue which I tracked down to a creation script missing a final GO statement.
Script 1
IF EXISTS (....)
DROP PROC MyProc
GO
CREATE PROC MyProc
.....
/* GO statement is missing */
Script 2
IF EXISTS (....)
DROP TRIGGER MyDisappearingTrigger
GO
CREATE TRIGGER MyDisappearingTrigger
.....
GO
When I inspected MyProc in the object explorer it looked like this:
CREATE PROC MyProc
AS
...
IF EXISTS (....)
DROP TRIGGER MyDisappearingTrigger
GO
So this meant that every time the stored proc was called the trigger was also deleted.

check with MERGE command in table it will cause triggers get error

Related

How to deduct a delete in postgresql

I have a weird problem where data in a postgresql table gets cleared completely daily. I don't see any scripts or anything that runs the delete query. Is there a way i can find which script/process deletes the data from the particular table?
You can see more about log_statement parameter. Set it to all so, all queries executed will be saved and you can do an analysis in what is happening with your database.
If you're on linux environment, the logs (normally) will be in /var/log/postgresql/local0.* files. And you can see what's happening.
Also, you can do more improvements on logs (like choose log only delete statements), as described on official documentation below.
More info at: https://www.postgresql.org/docs/9.5/runtime-config-logging.html
You will need to restart you postgres to the changes take effect.
Finally found a way to log the delete query even without restarting the server
Write a trigger function as below
CREATE OR REPLACE FUNCTION log_delete() RETURNS trigger AS $BODY$
BEGIN
RAISE LOG 'Deleting row % (statement is %)', OLD, current_query();
RETURN NULL;
END;
$BODY$ LANGUAGE plpgsql VOLATILE COST 100;
Call the trigger function by
CREATE TRIGGER ondelete
AFTER DELETE
ON public.tablename
FOR EACH ROW
EXECUTE PROCEDURE public.log_delete();
And that's it. your log will have the delete query that fired!
Ref : Postgresql - Determining what records are removed from a cascading delete

How to check the log when Trigger is turned On and Off

I want to check when my trigger is turned on and off in SQL Server 2005 database. I have created a trigger which inserts entry into new table whenever there is change in specific column. But I received a complaint from client saying that log is not maintained for all updated records in Log Table.
I feel it may be due to trigger is turned off while updating some records so it may not have been recorded in log table.
So how to see log record of whether trigger is turned on or off?
Thanks in advance.
Not quite clear what you're looking for.
Do you want to be able to check at any given time whether the trigger is on or off? In that case, use this statement:
SELECT is_disabled
FROM sys.triggers
WHERE name = 'your-trigger-name-here'
If you want to track when a given trigger is disabled, you could write a DDL trigger that catches the ALTER_TRIGGER event and makes a note of who and when a given trigger was disabled.
I put this answer for whom may search for this question.
You can use this statement to see more detail and the last modify date and time of trigger.
SELECT *
FROM sys.triggers
WHERE name = 'your-trigger-name-here'

changetable doesn't have current changes when in a trigger?

I have the following trigger to save the changes to a log table. However, it will not catch the changes triggered the trigger? Or is there another solution?
alter trigger trigger_xxx on table1 after delete, update, insert
as
begin
declare #lastVersion bigint = coalesce((select max(SYS_CHANGE_VERSION) from [log]), 0)
insert into [log]
([SourceColumnDescriptionPattern], SYS_CHANGE_VERSION, SYS_CHANGE_OPERATION, SYS_CHANGE_COLUMNS, SYS_CHANGE_CONTEXT)
SELECT [SourceColumnDescriptionPattern], SYS_CHANGE_VERSION, SYS_CHANGE_OPERATION, SYS_CHANGE_COLUMNS, SYS_CHANGE_CONTEXT
FROM changetable(changes [table1], #lastVersion) as ct
end
Change Tracking is intended for synchronization purposes. For example you can use it to find out if a application side cache needs to be refreshed. Therefore you do not want for that information to show up before the transaction is committed. As your trigger executes within the transaction the changes are not visible yet.
Why are you trying to duplicate the information available in Change Tracking? Cant you just use those functions and DMVs instead of your own?
Assuming you have a good reason, your best bet is probably to use a trigger and capture the affected primary key together with other pertinent information like a timestamp yourself. However there is no real good way to enforce that trigger being executed before all others so you might still end up in the same situation. You could try sp_settriggerorder in your case: http://msdn.microsoft.com/en-us/library/ms186762.aspx It might be enough in your situation.

ADOQuery is bypassing instead of delete trigger

I´m using Delphi 5 with SQL Server 2000 here.
I have created an ADOQuery on top of an updatable view with an INSTEAD OF DELETE trigger.
The updatable view is basically used for controlling soft deletes. It filters out records which are marked as deleted and it hides the controlling column as well.
It all works fine when I´m issuing direct DELETE commands to the database. I delete the record on the view and the underlying table gets updated, doing the soft delete as expected.
When I try to use the ADOQuery to delete a record, it bypasses the view and deletes the record directly on the underlying table, so the instead-of-delete trigger on the view is never fired.
I´m also using referential constraints and the delete is erroring out because of them, but I don´t know if this matters. This does not happen when issuing delete commands to the view.
Would any of you guys know how to work around this annoying behaviour?
Notice that it's deleting directly from the main table instead? This is probably because it's detecting that it's a view and working with the underlying table itself. To prevent this, declare your view WITH VIEW_METADATA, see ALTER VIEW for more information.
Then the ADO library will treat the view as a table. Be aware that you could get unwanted side effects by tricking your DB library like this, such as in cases when the delete isn't actually performed or it does an update instead of a delete.

How can I find out when a Sql Database field gets modified?

One of my database fields in a table is getting modified by some piece of code. I just can't figure out where!
So, I was wondering if there's a way I can find out.
I'm using SQL 2008. Can Profiler be used to find out if a particular field is getting updated? How?
What about a Trigger? If using a trigger (eg. on UPDATE) can you determine what code called it? How can the trigger 'notify me' of this? Email/file?
Yes, an "AFTER UPDATE" trigger on that particular table and field might give you some clues as to when and why the field gets changed.
From Books Online:
CREATE TRIGGER reminder
ON Person.Address
AFTER UPDATE
AS
IF ( UPDATE (StateProvinceID) OR UPDATE (PostalCode) )
BEGIN
RAISERROR (50009, 16, 10)
END;
GO
A trigger can execute basically any T-SQL code - if you have database mail set up correctly, it could send you an e-mail, yes. Or it can write an audit entry into another table or something like that.
EDIT: If you need to find out which statements updated your column, you might be actually better off running a trace on the server, limited to that specific table, and just trace what's happening there. I don't think a trigger can give you that information (which code caused the update to happen).
Marc
Determining the last Update to or Select against a table (without a trigger!)
http://sqlblogcasts.com/blogs/tonyrogerson/archive/2007/06/03/determining-the-last-update-to-or-select-against-a-table-without-a-trigger.aspx
Yes, you can use a trigger to execute some code (keep track of who updated the table, email you, etc.) when a table is updated. See this link: Track Updates with a Database Trigger
edit: originally posted the wrong link

Resources