Get database name from DDL Trigger - sql-server

I am creating a server level trigger in SQL 2008 to log table creation and drops. I need to log the database that the table was created in/dropped from. First I created a column with a default value of db_name(), but this always recorded master. Next I tried using this in my insert statement:
EVENTDATA().value('(/EVENT_INSTANCE/DatabaseName)[1]','nvarchar(max)')
This worked for a while, but suddenly it started recording master for all table creations and drops regardless of the database the table was in. All of the table drops have been done using SSMS. Does anyone know why I am seeing this behavior? Even more important, does anyone know how to log the correct database?
EDIT: I found an article which makes me think what I'm doing is incorrect. Apparently you should only capture create_table and drop_table from a database scoped trigger and not from a server_scoped trigger. I would still like to leave the question open though in case someone knows how to work around this.

HI,
You are correct, CREATE TABLE and DROP TABLE events should be recorded from within DDL Triggers that are defined at the database level.
Server Level Triggers are intended for server wide events, for example, when a Login occurs.
Here is an excellent article that may assist you in your developments.
http://www.developer.com/db/article.php/3552096
The following refence details which DDL events can be fired at either Database or Server scope.
http://msdn.microsoft.com/en-us/library/ms189871(SQL.90).aspx
Cheers,

Related

Get tablename at the start of event trigger in PostgreSQL

I am looking for the possibility to capture the name of a table on CREATE TABLE, DROP TABLE and other operations in my postgres database.
I looked into event triggers and they seem to only be able to capture these events on ddl_command_end (https://www.postgresql.org/docs/current/functions-event-triggers.html#PG-EVENT-TRIGGER-SQL-DROP-FUNCTIONS), which should work for the CREATE case but not all of the others.
So I wanted to ask, if there exists a possibility to either get the data from a dropped table (as I would need it) or get the information before the event happens.
Thank you for your help!
In Oracle we have a option to recover table but in PostgreSQL we do not have that option. Only thing you can do for this kind of situation enabling archiving and following PITR steps. It could be on other server or on the server that your database running. It depends on significance of the dropped table and the database.

Checking what 'DROP' queries were ran on SQL Server

Some one keeps dropping tables on one of our database's as soon as I gain access the server. I don't know who this some one is. I have nearly lost my job once because of this person.
So I was wondering is there a way I can check which user ran a query for DROP TABLE my_table so that I can prove to my boss I am innocent?
I found this article which may help you.
On SQL Server 2005 or newer, you could also investigate DDL triggers which would even allow you to prohibit certain DROP TABLE statements....
CREATE TRIGGER safety
ON DATABASE
FOR DROP_TABLE
AS
PRINT 'You must disable Trigger "safety" to drop tables!'
ROLLBACK
;
This would basically just prevent anyone from dropping a table

SQL Server : get at the name of the app causing an update in a trigger

We're trying to pinpoint the source of some unexpected updates happening on a SQL Server table. What I'd like to do is create a trigger on that table monitoring that column we're interested in, and when updates occur, write some audit info into a separate table.
Works great and fine for things like user name, date, old and new columns values (from the Inserted and Deleted trigger tables) - but I'd like more :-)
In SQL Profiler, you can see the name of the app that's connected to SQL Server in the profiles - the part that can be defined in the connection string as Application Name:
Data Source=(local);Initial Catalog=AdventureWorks;
Integrated Security=True;Application Name="My Application"
Is there any way in a T-SQL FOR UPDATE trigger to get at this information?
SELECT APP_NAME()
Marc_S the sP_whoIsActive stored Procedure probably will solve Your problems
as posted here
and it's awesome part of T-SQL by the way
Not sure but could you possibly log the server name if you applications are on multiple servers? It might help narrow down the list of applications.

notification that table rows have been changed

When the table's rows are changed, these changed rows are written to XML, and let me know that the table has been changed.
How can I do this?
If you're looking for a strict TSQL or SQL Server solution:
write a stored procedure to handle UPDATE, DELETE and INSERT functionality.
deny UPDATE, DELETE and INSERT to users
allow EXEC to users on this new stored proc
on each call to the stored proc, make an entry into another table, specifically built for auditing.
write a SQL Job to poll this audit table for new records. Use SQL Mail to send email. You weren't clear about what kind of notification you wanted, but I assumed email.
2nd less attractive solution: You could also use triggers on the table to capture the UPDATE, DELETE and INSERT activity. Strongly consider the stored proc solution over triggers.
If you can't alter how data is being changed in your table, the best solution would be to setup a trigger to capture changes in a separate table, and then write some code to periodically poll this table, and build your xml file.
Its worth noting that this will potentially slow down your db performance when editing data in this table (good for audit when users are making changes, bad for programatically changed data), and any errors coming from the trigger lead to quite misleading messages thrown back out of sql server.
See this question for some pointers on setting up the trigger.

What sort of audit information is stored by sql server when a CREATE TABLE or ALTER TABLE operation is performed?

The inspiration for this question is a stored proc broke on me because it called another stored proc that inserted data in a table whose schema was completely altered.
The question is you have a table in a SQL Server database, and you don't know how it got there. You don't have any DDL triggers in place for custom audit information, and there is no record in your source control repository of the tables DDL. Using only SQL Server, what forensic data can you obtain about the table.
Myself, and whoever stumbles across this question in a similar situation, is not going to be helped by suggestions regarding version control and DDL triggers. Those are great go forward solutions, and there is plenty of info on this blog about those topics, if corporate politics allows us to implement those solutions. What I, and people in my situation really need is to be able to gather as many fragments of data as possible from SQL server, to combine with whatever other data we can come up with.
Unfortunately, you have no way to reconstruct what happened, except:
if the DBAs have traces running and the history. SQL Server 2005 has a default trace and there is the "blackbox" trace, but these are used to find out what happened right before a crash
if you have FULL recovery model, then you can try a log viewer tool (free Red Gate one)
depending on activity and your security model, you could also check the Windows Security Log to see who logged in with DDL privileges
the SQL event logs may also have information. For example, if you have enabled the trace flag that logs "permission" errors, then you can see when it started. Or the person who made the change may have generated other exceptions that are logged
you could ask those with rights. It could be a genuine mistake (eg thought they were in dev)
The following query got me the create and last modify time.
SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[tbTableInQuestion]') AND type in (N'U')
You should be able to find the creation of the table in the transaction log. I have never used any of the viewer tools here, and I couldn't tell you how to search back in time for this, but everything happens in a transaction, so it's gotta be logged -- even the system tables...

Resources