FOR/AFTER in SQL triggers - sql

I am newbie in SQL. I am reading about Triggers in SQL.I have got almost about Triggers. But in DML Triggers, we use FOR/AFTER keyword. I didn't get difference between FOR/AFTER and why we use FOR/AFTER keyword. I have already read on MSDN but didn't get the simple answer.
Can anyone explain me what is it?
Thanks in advance.

There is no difference between using FOR and AFTER.
I believe the original (pre 2000) syntax only used the FOR keyword. However, when INSTEAD OF triggers were introduced, the "FOR" keyword could seem quite confusing. "AFTER" more accurately conveys the type of trigger, and is more easily distinguished from "INSTEAD OF".
An INSTEAD OF trigger would be used if we wanted to transform what was inserted into the table, or prevent an insertion from taking place.
An AFTER trigger would more normally be used if we wanted to perform additional tasks, based on what has just occurred. For instance, you could have an "AFTER DELETE" trigger, that copied deleted rows into some kind of archive table. Basically, in an AFTER trigger, you more normally do still want the activity to occur.

From MSDN:
AFTER triggers are never executed if a constraint violation occurs; therefore, these triggers cannot be used for any processing that might prevent constraint violations.
And then:
You can request AFTER triggers by specifying either the AFTER or FOR keywords. Because the FOR keyword has the same effect as AFTER, DML triggers with the FOR keyword are also classified as AFTER triggers
It would seem there is no difference.

If I interpret your comments to the other answers correctly, you want to know why or when one uses the "FOR|AFTER" keywords.
It's simple: there are two kinds of triggers, the AFTER-trigger and the INSTEAD-OF-trigger.
The INSTEAD-OF-trigger for e.g. an insert action can be written as
create trigger myTrigger on myTable
INSTEAD OF insert
begin
(... code goes here ...)
end
and the AFTER-trigger can be written as either
create trigger myTrigger on myTable
AFTER insert
begin
(... code goes here ...)
end
or
create trigger myTrigger on myTable
FOR insert
begin
(... code goes here ...)
end
As Damien_The_Unbeliever mentions, the AFTER keyword is more readable than the FOR version, that is all.

They are the same. See this excerpt from BOL
"
FOR | AFTER
AFTER specifies that the DML trigger is fired only when all operations specified in the triggering SQL statement have executed successfully. All referential cascade actions and constraint checks also must succeed before this trigger fires.
AFTER is the default when FOR is the only keyword specified.
AFTER triggers cannot be defined on views.
"

According to what I observe, FOR is used in DDL trigger while AFTER is used in DML triggers. They have same way of working.

Related

Is the BEFORE Trigger statement executed before the DDL statement?

Is the BEFORE trigger statement executed before DDL statements or is it inside a DDL statement?
I'm building a small DBMS and currently developing the DDL, and I'm confused about handling the BEFORE statement.
Here's not a defined behaviour for it:
https://web.csulb.edu/colleges/coe/cecs/dbdesign/dbdesign.php?page=sql/ddldml.php
Oracle describes the behaviour but not what can come inside the preceding or following trigger or whether they can be DDL statements or not:
https://www.oracletutorial.com/plsql-tutorial/oracle-trigger/
"BEFORE" is part of the DDL statement that defines the trigger. It describes when the trigger fires in relation to a DML command on a table: i.e. BEFORE or AFTER the change to the data is actually made. This allows you to validate or modify the new data as it is being applied, or to add or modify dependent data like a child table after the parent table update is complete.
While you can technically embed DDL into the body of a trigger using "execute immediate", it is typically considered very bad practice to do so. Is there a specific use case you are considering for including DDL statements in a trigger?

Is it possible to create a trigger that creates another trigger

Is it possible to have a trigger that creates another trigger?
For example, I have table_1 with a column table_name. On inserting into table_1 the first trigger would create a trigger for the table inserted as table_name? I have not found much info on this.
Trigger enables you to run dynamic SQL, in which you can create what objects you like, including other triggers (assuming you have the right permissions).
You can do that by using sp_executesql, it executes a Transact-SQL statement or batch that can be reused many times, or one that has been built dynamically. The Transact-SQL statement or batch can contain embedded parameters
This seems tough as a (very) bad design. So go ahead and try that (or not*).
*You can state your problem to begin with, may be in programmers (if it's more a design oriented question) or in Database Administrators, and you may get better help.

Is it possible to update trigger table in update trigger?

I have an update trigger for a table. When I am updating the table rows I need to check certain condition in trigger then based on that I want to update another column.
Is it possible?
You might want to read the documentation for CREATE TRIGGER, especially the remarks section, which includes:
If an INSTEAD OF trigger defined on a table executes a statement against the table that would ordinarily fire the INSTEAD OF trigger again, the trigger is not called recursively. Instead, the statement is processed as if the table had no INSTEAD OF trigger and starts the chain of constraint operations and AFTER trigger executions.
If this, or other parts of the remarks section, don't answer your questions, you probably need to add more to your question about what problems you're having, or what issues you're concerned about.

Difference between FOR and AFTER triggers?

What's the difference between FOR and AFTER triggers?
There is no difference, they do the same thing.
CREATE TRIGGER trgTable on dbo.Table FOR INSERT,UPDATE,DELETE
Is the same as
CREATE TRIGGER trgTable on dbo.Table AFTER INSERT,UPDATE,DELETE
An INSTEAD OF trigger is different, and fires before and instead of the insert and can be used on views, in order to insert the appropriate values into the underlying tables.
#Ben is absolutely right.
Here is MSDN article Exploring SQL Server Triggers
A paragraph from the article:
That syntax is also acceptable in older versions of SQL Server. However, now that there are two types of triggers in SQL Server 2000, I prefer to refer to FOR triggers as AFTER triggers. Thus, for the remainder of this article I will refer to either AFTER or INSTEAD OF triggers.
Like the AFTER trigger you saw earlier, this trigger prevents changes from being made to the lastname field. However, it implements this business rule differently than the previous example. Because the INSTEAD OF trigger fires in place of the UPDATE statement, the INSTEAD OF trigger then evaluates if the business rule test passes or not. If the business rule test passes, in order for the update to occur the INSTEAD OF trigger must explicitly invoke the UPDATE statement again.
AFTER specifies that the DML trigger is fired only when all operations specified in the triggering SQL statement have executed successfully. All referential cascade actions and constraint checks also must succeed before this trigger fires.
AFTER is the default when FOR is the only keyword specified.
AFTER triggers cannot be defined on views.
INSTEAD OF
Specifies that the DML trigger is executed instead of the triggering SQL statement, therefore, overriding the actions of the triggering statements. INSTEAD OF cannot be specified for DDL or logon triggers.
https://learn.microsoft.com/en-us/sql/t-sql/statements/create-trigger-transact-sql

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.