Get caller of trigger in SQL Server - sql

Can you advice me how I can retrieve caller ID or Name which executed a trigger?
For example I want to know which SP executes a trigger or maybe trigger called by updates from management studio?
I know that ##PROCID returns ID of trigger and can't be used.
Also I know solution when in SP we write CONTEXT_INFO and read it from trigger.
But in this case we should SET CONTEXT_INFO in all SPs that modifies some table.
Is there exists some simplest way like ##PROCID ?

If it's SQL Server 2005 or 2008, and a DDL trigger, you can use eventdata().
Here's a link to the msdn page.
Basically it returns an XML dataset that you can parse to get things like who called it (data(/EVENT_INSTANCE/LoginName)[1]), what the command was, etc.

Related

Under what circumstances are SQL Server triggers executed?

The database I'm working on has a trigger which calls a stored procedure which takes 42 seconds to run if I do an UPDATE using T-SQL. If I edit the row in SQL Server Management Studio, the row updates instantly. Triggers are executed in the edit window as well as on T-SQL UPDATES, aren't they?
The SQL code in the stored procedure comes back instantly if I run it directly or call it using EXEC, the only circumstances when it runs slowly are when the trigger is called by an UPDATE statement.
It depends how the trigger was set up, Triggers will only run on Update, Delete and Insert statements (Depending which of the three are chosen) On the table it is set against.
Could you give the code used to create the trigger?
These triggers run after an insert, update or delete on a table
click here for details about different type of triggers and demo for triggers

sql server trigger to update another database whenever a sproc is created

Is there a way to update another database with the newly created stored procedure whenever a stored procedure is created in the main database?
For example, i have two databases, DB1 and DB2.
When I create a stored procedure in DB1, i want that same procedure to created in DB2 automatically? Is there a trigger that can do this?
USE [DB1]
CREATE PROCEDURE [dbo].[TestSproc]
..something
AS
BEGIN
...something
END
I know a use [DB2] statement will do the job, but i want this to be done automatically. Any thought?
Thanks for the help!
This might be a bit evil, but in SQL Server you are able to create DDL triggers which fire when you create/alter/drop tables/procedures etc. The syntax to fire when a procedure is created is:
CREATE TRIGGER <proc-name>
ON DATABASE
FOR CREATE_PROCEDURE
AS
--Your code goes here
In a DDL trigger you get access to an object called EVENTDATA. So to get the text of the procedure you created:
SELECT EVENTDATA().value('(/EVENT_INSTANCE/TSQLCommand/CommandText)[1]','nvarchar(max)')
Now all you need to do is keep that value and execute it in your secondary database. So your query becomes something like this, though I leave the code to update the secondary database down to you as I don't know if it's on the same server, linked server etc.:
CREATE TRIGGER sproc_copy
ON DATABASE
FOR CREATE_PROCEDURE
AS
DECLARE #procedureDDL AS NVARCHAR(MAX) = EVENTDATA().value('(/EVENT_INSTANCE/TSQLCommand/CommandText)[1]','nvarchar(max)')
--Do something with #procedureDDL
As this is not tested, there's probably a few gotchas. For example, what happens if you create procedure with full name (CREATE PROC server.database.schema.proc)
No simple solution for this unless you want to execute the same statement twice, once on each target database,
One thing that comes to my mind is that you can Set up Replication and only publish Stored Procedures to your second database which will be the subscriber in this case.
Following is the window where you select which Objects you want to send over to your secondary databases.

C# SQL transaction

I am using a C# class that is calling a SQL stored procedure in a serializable transaction.
So if something goes wrong in the stored procedure, everything is rolled back.
I have one statement in the SQL stored procedure that should be always executed (even if the stored procedure fails at some point and a rollback occurs). The statement is an update of a record.
I cannot change the C# library, so I need to do this in my stored procedure.
Is there some way I can execute that one statement outside the transaction?
You could perhaps use SAVE TRANSACTION. It is not supported in distributed transactions, and your statement must be executed first, so it might not be what you are looking for.
I have found the solution.
I didn't realize that SQL knew it was called in a transactional matter by the c# class.
The update statement that should always be executed is the first step (and also last step) in the procedure. Let me clarify:
I have an IF function. If it is true, the update should occur no matter what. If it is false, some transactional logic should be executed.
Now in the c# class, it expects a result from the stored proc. If the proc doesn't return a result (like it does in the update statement), it rollbacks the transaction.
So by just adding the following lines right after the update statement, the update occurs :)
IF ##TRANCOUNT > 0
BEGIN
COMMIT TRANSACTION
END
Your solution does not sound like a good one.. For example- if your stored procedure will be part of bigger transaction, then it will commit all changes made before it. Also I believe no one would guess that your proc has such behaviour without first seeing code.
The need to always execute some part of proc sounds like need for security audit. So maybe you should use trace, extended events or sql server audit instead.
if you really need what you say you need- you can use method described here: How to create an autonomous transaction in SQL Server 2008

Alter All Triggers via T-SQL

Is there a way to update/alter all triggers using Looping T-SQL or a C# Code ?. I need it too update all the triggers in my database because the RAISERROR command has changed in sql server 2012.
You can script out all the triggers into a text file. See:
How to Generate Scripts For All Triggers in Database Using Microsoft SQL Server Management Studio
Then, you can use a text editor to replace the code you need to replace. Then, you can drop your triggers and recreate them. I don't know if your referring to a production database, or one that you are doing development on. I am assuming from your question that you are prepared to make these major changes to your database. Make sure you back up your database first, in any event.
You can get all trigger using
SELECT [name] FROM [sys].[triggers]
and loop through each trigger and execute
EXEC sp_helptext 'TriggerName'
so you will have the create statement with it...

Pre-insert/update trigger in SQL Server

All we need is to create several pre-insert/update triggers in SQL Server 2008 R2 which do some select * or select count(*) and explicitly fail if it is empty or non-empty.
Please, how to achieve that?
Create an INSTEAD OF INSERT, UPDATE trigger. Now to prevent DML you have 2 options. In the body of trigger execute RAISERROR so your application can catch the error. Another way is not to perform actual insert/update in the trigger, so no records will be inserted/updated, but the user will not know if DML succeeds.