SQL Server: Don´t execute a Trigger when the updater is another trigger - sql

Here is the scenario:
There is Trigger A and Trigger B, both in the Person table. I can't trigger the Trigger A when the update on table Person comes from Trigger B.
Is there something, such as an IF that I could use to solve this situation?
Thanks in advance for any help!

Right at the start, I will warn you that having multiple triggers on one table is not a good idea. Try and merge the actions of the two triggers into one if possible. However, if that is not a solution for you, then read on for my version. (I am not certain if it is practically valid, but go ahead and give it a shot anyway)
CREATE TRIGGER triggerB
ON yourtable
FOR UPDATE
AS
BEGIN
ALTER TABLE table_name DISABLE TRIGGER triggerA
--your processing
ALTER TABLE table_name ENABLE TRIGGER triggerA
END
This question deals with disabling then enabling triggers inside a stored procedure. This is an application of the same in a trigger.
Disclaimer: I am counting on this to fail because altering a table while in a trigger defined on that same table seems like an impossible task. But I have no resources at hand to test my wacky theory, so please test it and let me know if I'm thinking too far outside the box.

I got it!
IF TRIGGER_NESTLEVEL(OBJECT_ID('TRIGGER_NAME')) = 0
BEGIN
-- Your Trigger STuff
END
Thanks for answers and comments.

Related

Trigger: Trigger if someone INSERT,UPDATE and DELETE a table

I have a trigger created that will log their username to ChangesLogtbl if they update, delete or insert in TblCurrentRec.
CREATE TRIGGER mytriggerforinsert
#username = username <------------------itried to place something like this
ON TblCurrentRec
AFTER INSERT
AS BEGIN
INSERT INTO ChangesLogtbl
values ('username', 'GETDATE')
END
GO
This works but I want this one to work on all tables within the schema. and also not to limit it on insert but to delete and update as well.
I tried using everything in and over the net and also copied and studied different sample but to no avail. I'm new to SQL and this is my very first time to create a trigger. Hope you guys can understand.
Thanks.
TO cover other DML,
ON TblCurrentRec
AFTER INSERT or UPDATE or DELETE
Coming to schema level coverage, i doubt you can have a single trigger for all tables in schema.Triggers should be written to each table.
If it where DDL we can use DATABASE TRIGGERS
You can use of cursors and the Information_Schema.Tables view to create triggers on all tables of a database.

Trigger when a select occurs

i have a customer with a ERP wich i don't have programming access, and wants to do a special trigger when a item is selected. The problem is that the ItemID is nowhere kept when chosen, only when whole sale is kept, and the trigger should happen before that.
This is a novice question for sure, but this value must be kept somewhere right ?
When i do a audit do see what happens when the item is chosen inside the ERP it only does SELECT statments. Can i do a trigger based on a SELECT ?
Thank you.
It is not possible to create a trigger based on execution of a select query in PL/SQL. Trigger can be created only on INSERT, UPDATE or DELETE.
References :
https://community.oracle.com/thread/1556647?tstart=0
http://www.geekinterview.com/question_details/18571

Can you disable a trigger within a trigger? SQL Server 2008

Can you disable and re-enable triggers within a trigger?
For example, I have a piece of information in a front-end application that can be put in one of two places. If someone puts it in place A, I want to copy it to place B and vice versa.
So, my idea is to put two triggers on the different tables 1) When it's put in A it puts it in B. 2) When it's put in B it puts it in A
This would create a neverending loop (I assume?) so can you disable Trigger 1 while Trigger 2 runs and enable it at the end?
Although I agree with Damien's comment that duplicating data in two tables in the same database is generally undesirable, if you really have a good reason for doing this then you could use INSTEAD OF triggers instead of AFTER triggers (which I assume you're looking at now). That way you can 'replace' a single INSERT with two separate INSERTs that you code and control yourself.
Yes you can:
ALTER TABLE tablename DISABLE TRIGGER triggername
ALTER TABLE tablename ENABLE TRIGGER triggername
Although, for your solution, I'd create a trigger that runs the same on each side, and is clever enough not to mess itself up.
i.e. Make the trigger intelligently distinguish between a user/client INSERT and a trigger 'MOVE'.
Or you could check whether the information had changed in the trigger before doing the update, which would end the loop?

Should I use the template from MS SQL Management Studio to create new triggers?

If you create a new trigger in MS SQL Management Studio by using the GUI, it gives you this template:
--====================================
-- Create database trigger template
--====================================
USE <database_name, sysname, AdventureWorks>
GO
IF EXISTS(
SELECT *
FROM sys.triggers
WHERE name = N'<trigger_name, sysname, table_alter_drop_safety>'
AND parent_class_desc = N'DATABASE'
)
DROP TRIGGER <trigger_name, sysname, table_alter_drop_safety> ON DATABASE
GO
CREATE TRIGGER <trigger_name, sysname, table_alter_drop_safety> ON DATABASE
FOR <data_definition_statements, , DROP_TABLE, ALTER_TABLE>
AS
IF IS_MEMBER ('db_owner') = 0
BEGIN
PRINT 'You must ask your DBA to drop or alter tables!'
ROLLBACK TRANSACTION
END
GO
Should I use this template?
I dont know anything about triggers, but I think I need to use them. The purpose in this case is that on an insert to the table, I need to update one of the fields.
Please help me get started!
OK to begin with that is the wrong template if you want an ordinary trigger that one is a trigger on making structural changes to the table itself.
If you decide to do a trigger that affects data (as opposed to structure), there are several things you need to know. First and by far the most critical, triggers operate on sets of data not one row at time. You must write any trigger to handle multiple row inserts.updates or deletes. If you end up with any code setting the value in inserted or deleted to a variable, there is a 99% chance it will not work properly if multiple records are involved.
What is inserted or deleted you ask? That is the next thing you need to know about triggers, there are two pseudotables (inserted and deleted) that are only available in a trigger (or an output clause) which contain the new information being inserted or the updated values (in the inserted table) and the old information being deleted or being changed by an update (in the deleted table). So an insert has values in inserted, a delete has values in deleted and an update has values in both. Use these in your trigger to pull the values you need to change.
Since you don't know anything about triggers, I would say no, don't use the template.
Read the books online page for Create Trigger and write the trigger by hand.
There is probably more in that template code than you actually need. Read the manual and keep it simple.
If you don't know anything about triggers then I would strongly suggest that you read up on them before implementing them. Get Triggers right and they can make your life a lot easier; get it wrong and Triggers will cause you a lot of trouble.
I would suggest starting off with this tutorial
http://www.sqlteam.com/article/an-introduction-to-triggers-part-i
You can use the above SQL as a template or you can simply write your own. I would suggest you write your own as you'll understand what you are doing. Obviously only do this after you have done some serious reading on triggers. Check out MSDN too

How do you priortize multiple triggers of a table?

I have a couple of triggers on a table that I want to keep separate and would like to priortize them.
I could have just one trigger and do the logic there, but I was wondering if there was an easier/logical way of accomplishing this of having it in a pre-defined order ?
Use sp_settriggerorder. You can specify the first and last trigger to fire depending on the operation.
sp_settriggerorder on MSDN
From the above link:
A. Setting the firing order for a DML trigger
The following example specifies that trigger uSalesOrderHeader be the first trigger to fire after an UPDATE operation occurs on the Sales.SalesOrderHeader table.
USE AdventureWorks;
GO
sp_settriggerorder
#triggername= 'Sales.uSalesOrderHeader',
#order='First',
#stmttype = 'UPDATE';
B. Setting the firing order for a DDL trigger
The following example specifies that trigger ddlDatabaseTriggerLog be the first trigger to fire after an ALTER_TABLE event occurs in the AdventureWorks database.
USE AdventureWorks;
GO
sp_settriggerorder
#triggername= 'ddlDatabaseTriggerLog',
#order='First',
#stmttype = 'ALTER_TABLE',
#namespace = 'DATABASE';
See here.
You can use sp_settriggerorder to define the order of each trigger on a table.
However, I would argue that you'd be much better off having a single trigger that does multiple things. This is particularly so if the order is important, since that importance will not be very obvious if you have multiple triggers. Imagine someone trying to support the database months/years down the track. Of course there are likely to be cases where you need to have multiple triggers or it really is better design, but I'd start assuming you should have one and work from there.
Rememebr if you change the trigger order, someone else could come by later and rearrange it again. And where would you document what the trigger order should be so a maintenance developer knows not to mess with the order or things will break? If two trigger tasks definitely must be performed in a specific order, the only safe route is to put them in the same trigger.