Skip to content

Commit 6616342

Browse files
author
PRMerger6
authored
Merge pull request #5358 from MashaMSFT/2018030_TriggerOptimization
2018030 trigger optimization
2 parents cdf09d6 + c107fcd commit 6616342

1 file changed

Lines changed: 43 additions & 23 deletions

File tree

docs/t-sql/statements/create-trigger-transact-sql.md

Lines changed: 43 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -35,14 +35,15 @@ caps.latest.revision: 140
3535
author: "edmacauley"
3636
ms.author: "edmaca"
3737
manager: "craigg"
38+
ms.reviewer: mathoma
3839
ms.workload: "Active"
3940
---
4041
# CREATE TRIGGER (Transact-SQL)
4142
[!INCLUDE[tsql-appliesto-ss2008-asdb-xxxx-xxx-md](../../includes/tsql-appliesto-ss2008-asdb-xxxx-xxx-md.md)]
4243

43-
Creates a DML, DDL, or logon trigger. A trigger is a special kind of stored procedure that automatically executes when an event occurs in the database server. DML triggers execute when a user tries to modify data through a data manipulation language (DML) event. DML events are INSERT, UPDATE, or DELETE statements on a table or view. These triggers fire when any valid event is fired, regardless of whether or not any table rows are affected. For more information, see [DML Triggers](../../relational-databases/triggers/dml-triggers.md).
44+
Creates a DML, DDL, or logon trigger. A trigger is a special type of stored procedure that automatically executes when an event occurs in the database server. DML triggers execute when a user tries to modify data through a data manipulation language (DML) event. DML events are INSERT, UPDATE, or DELETE statements on a table or view. These triggers fire when any valid event is fired, regardless of whether or not any table rows are affected. For more information, see [DML Triggers](../../relational-databases/triggers/dml-triggers.md).
4445

45-
DDL triggers execute in response to a variety of data definition language (DDL) events. These events primarily correspond to [!INCLUDE[tsql](../../includes/tsql-md.md)] CREATE, ALTER, and DROP statements, and certain system stored procedures that perform DDL-like operations. Logon triggers fire in response to the LOGON event that is raised when a user sessions is being established. Triggers can be created directly from [!INCLUDE[tsql](../../includes/tsql-md.md)] statements or from methods of assemblies that are created in the [!INCLUDE[msCoName](../../includes/msconame-md.md)] [!INCLUDE[dnprdnshort](../../includes/dnprdnshort-md.md)] common language runtime (CLR) and uploaded to an instance of [!INCLUDE[ssNoVersion](../../includes/ssnoversion-md.md)]. [!INCLUDE[ssNoVersion](../../includes/ssnoversion-md.md)] allows for creating multiple triggers for any specific statement.
46+
DDL triggers execute in response to a variety of data definition language (DDL) events. These events primarily correspond to [!INCLUDE[tsql](../../includes/tsql-md.md)] CREATE, ALTER, and DROP statements, and certain system stored procedures that perform DDL-like operations. Logon triggers fire in response to the LOGON event that is raised when a user's session is being established. Triggers can be created directly from [!INCLUDE[tsql](../../includes/tsql-md.md)] statements or from methods of assemblies that are created in the [!INCLUDE[msCoName](../../includes/msconame-md.md)] [!INCLUDE[dnprdnshort](../../includes/dnprdnshort-md.md)] common language runtime (CLR) and uploaded to an instance of [!INCLUDE[ssNoVersion](../../includes/ssnoversion-md.md)]. [!INCLUDE[ssNoVersion](../../includes/ssnoversion-md.md)] allows for creating multiple triggers for any specific statement.
4647

4748
> [!IMPORTANT]
4849
> Malicious code inside triggers can run under escalated privileges. For more information on how to mitigate this threat, see [Manage Trigger Security](../../relational-databases/triggers/manage-trigger-security.md).
@@ -54,7 +55,7 @@ ms.workload: "Active"
5455

5556
## Syntax
5657

57-
```
58+
```sql
5859
-- SQL Server Syntax
5960
-- Trigger on an INSERT, UPDATE, or DELETE statement to a table or view (DML Trigger)
6061

@@ -76,7 +77,7 @@ AS { sql_statement [ ; ] [ ,...n ] | EXTERNAL NAME <method specifier [ ; ] > }
7677

7778
```
7879

79-
```
80+
```sql
8081
-- SQL Server Syntax
8182
-- Trigger on an INSERT, UPDATE, or DELETE statement to a
8283
-- table (DML Trigger on memory-optimized tables)
@@ -95,7 +96,7 @@ AS { sql_statement [ ; ] [ ,...n ] }
9596

9697
```
9798

98-
```
99+
```sql
99100
-- Trigger on a CREATE, ALTER, DROP, GRANT, DENY,
100101
-- REVOKE or UPDATE statement (DDL Trigger)
101102

@@ -111,7 +112,7 @@ AS { sql_statement [ ; ] [ ,...n ] | EXTERNAL NAME < method specifier > [ ; ]
111112

112113
```
113114

114-
```
115+
```sql
115116
-- Trigger on a LOGON event (Logon Trigger)
116117

117118
CREATE [ OR ALTER ] TRIGGER trigger_name
@@ -128,7 +129,7 @@ AS { sql_statement [ ; ] [ ,...n ] | EXTERNAL NAME < method specifier > [ ; ]
128129

129130
## Syntax
130131

131-
```
132+
```sql
132133
-- Windows Azure SQL Database Syntax
133134
-- Trigger on an INSERT, UPDATE, or DELETE statement to a table or view (DML Trigger)
134135

@@ -144,7 +145,7 @@ ON { table | view }
144145

145146
```
146147

147-
```
148+
```sql
148149
-- Windows Azure SQL Database Syntax
149150
-- Trigger on a CREATE, ALTER, DROP, GRANT, DENY,
150151
-- REVOKE, or UPDATE STATISTICS statement (DDL Trigger)
@@ -246,11 +247,11 @@ OR ALTER
246247

247248
The trigger actions specified in the [!INCLUDE[tsql](../../includes/tsql-md.md)] statements go into effect when the operation is tried.
248249

249-
Triggers can include any number and kind of [!INCLUDE[tsql](../../includes/tsql-md.md)] statements, with exceptions. For more information, see Remarks. A trigger is designed to check or change data based on a data modification or definition statement; it should not return data to the user. The [!INCLUDE[tsql](../../includes/tsql-md.md)] statements in a trigger frequently include [control-of-flow language](~/t-sql/language-elements/control-of-flow.md).
250+
Triggers can include any number and type of [!INCLUDE[tsql](../../includes/tsql-md.md)] statements, with exceptions. For more information, see Remarks. A trigger is designed to check or change data based on a data modification or definition statement; it should not return data to the user. The [!INCLUDE[tsql](../../includes/tsql-md.md)] statements in a trigger frequently include [control-of-flow language](~/t-sql/language-elements/control-of-flow.md).
250251

251252
DML triggers use the deleted and inserted logical (conceptual) tables. They are structurally similar to the table on which the trigger is defined, that is, the table on which the user action is tried. The deleted and inserted tables hold the old values or new values of the rows that may be changed by the user action. For example, to retrieve all values in the `deleted` table, use:
252253

253-
```
254+
```sql
254255
SELECT * FROM deleted;
255256
```
256257

@@ -273,7 +274,7 @@ SELECT * FROM deleted;
273274
> [!NOTE]
274275
> By default, the ability of [!INCLUDE[ssNoVersion](../../includes/ssnoversion-md.md)] to run CLR code is off. You can create, modify, and drop database objects that reference managed code modules, but these references will not execute in an instance of [!INCLUDE[ssNoVersion](../../includes/ssnoversion-md.md)] unless the [clr enabled Option](../../database-engine/configure-windows/clr-enabled-server-configuration-option.md) is enabled by using [sp_configure](../../relational-databases/system-stored-procedures/sp-configure-transact-sql.md).
275276
276-
## Remarks DML Triggers
277+
## Remarks for DML Triggers
277278
DML triggers are frequently used for enforcing business rules and data integrity. [!INCLUDE[ssNoVersion](../../includes/ssnoversion-md.md)] provides declarative referential integrity (DRI) through the ALTER TABLE and CREATE TABLE statements. However, DRI does not provide cross-database referential integrity. Referential integrity refers to the rules about the relationships between the primary and foreign keys of tables. To enforce referential integrity, use the PRIMARY KEY and FOREIGN KEY constraints in ALTER TABLE and CREATE TABLE. If constraints exist on the trigger table, they are checked after the INSTEAD OF trigger execution and before the AFTER trigger execution. If the constraints are violated, the INSTEAD OF trigger actions are rolled back and the AFTER trigger is not fired.
278279

279280
The first and last AFTER triggers to be executed on a table can be specified by using sp_settriggerorder. Only one first and one last AFTER trigger for each INSERT, UPDATE, and DELETE operation can be specified on a table. If there are other AFTER triggers on the same table, they are randomly executed.
@@ -289,7 +290,7 @@ SELECT * FROM deleted;
289290
For example, if a trigger is defined as an INSTEAD OF UPDATE trigger for a view, and the trigger executes an UPDATE statement referencing the same view, the UPDATE statement executed by the INSTEAD OF trigger does not call the trigger again. The UPDATE executed by the trigger is processed against the view as if the view did not have an INSTEAD OF trigger. The columns changed by the UPDATE must be resolved to a single base table. Each modification to an underlying base table starts the chain of applying constraints and firing AFTER triggers defined for the table.
290291

291292
### Testing for UPDATE or INSERT Actions to Specific Columns
292-
You can design a [!INCLUDE[tsql](../../includes/tsql-md.md)] trigger to perform certain actions based on UPDATE or INSERT modifications to specific columns. Use [UPDATE()](../../t-sql/functions/update-trigger-functions-transact-sql.md) or [COLUMNS_UPDATED](../../t-sql/functions/columns-updated-transact-sql.md) in the body of the trigger for this purpose. UPDATE() tests for UPDATE or INSERT tries on one column. COLUMNS_UPDATED tests for UPDATE or INSERT actions that are performed on multiple columns and returns a bit pattern that indicates which columns were inserted or updated.
293+
You can design a [!INCLUDE[tsql](../../includes/tsql-md.md)] trigger to perform certain actions based on UPDATE or INSERT modifications to specific columns. Use [UPDATE()](../../t-sql/functions/update-trigger-functions-transact-sql.md) or [COLUMNS_UPDATED](../../t-sql/functions/columns-updated-transact-sql.md) in the body of the trigger for this purpose. UPDATE() tests for UPDATE or INSERT attempts on one column. COLUMNS_UPDATED tests for UPDATE or INSERT actions that are performed on multiple columns and returns a bit pattern that indicates which columns were inserted or updated.
293294

294295
### Trigger Limitations
295296
CREATE TRIGGER must be the first statement in the batch and can apply to only one table.
@@ -326,9 +327,22 @@ SELECT * FROM deleted;
326327
|ALTER TABLE when used to do the following:<br /><br /> Add, modify, or drop columns.<br /><br /> Switch partitions.<br /><br /> Add or drop PRIMARY KEY or UNIQUE constraints.|||
327328

328329
> [!NOTE]
329-
> Because [!INCLUDE[ssNoVersion](../../includes/ssnoversion-md.md)] does not support user-defined triggers on system tables, we recommend that you do not create user-defined triggers on system tables.
330+
> Because [!INCLUDE[ssNoVersion](../../includes/ssnoversion-md.md)] does not support user-defined triggers on system tables, we recommend that you do not create user-defined triggers on system tables.
331+
332+
### Optimizing DML Triggers
333+
Triggers work in transactions (implied, or otherwise) and while they are open, they lock resources. The lock will remain in place until the transaction is confirmed (with COMMIT) or rejected (with a ROLLBACK). The longer a trigger runs, the higher the probability that another process will be blocked. Therefore, triggers should be written in a way to decrease their duration whenever possible. One way to achieve this is to release a trigger when a DML statement changes 0 rows.
334+
335+
To release the trigger for a command that that does not change any rows, employ the system variable [ROWCOUNT_BIG](https://docs.microsoft.com/it-it/sql/t-sql/functions/rowcount-big-transact-sql).
336+
337+
The following T-SQL code snippet will achieve this, and should be present at the beginning of each DML trigger:
338+
339+
```sql
340+
IF (@@ROWCOUNT_BIG = 0)
341+
RETURN;
342+
```
330343

331-
## Remarks DDL Triggers
344+
345+
## Remarks for DDL Triggers
332346
DDL triggers, like standard triggers, execute stored procedures in response to an event. But unlike standard triggers, they do not execute in response to UPDATE, INSERT, or DELETE statements on a table or view. Instead, they primarily execute in response to data definition language (DDL) statements. These include CREATE, ALTER, DROP, GRANT, DENY, REVOKE, and UPDATE STATISTICS statements. Certain system stored procedures that perform DDL-like operations can also fire DDL triggers.
333347

334348
> [!IMPORTANT]
@@ -388,7 +402,7 @@ SELECT * FROM deleted;
388402
### Nested Triggers
389403
Triggers can be nested to a maximum of 32 levels. If a trigger changes a table on which there is another trigger, the second trigger is activated and can then call a third trigger, and so on. If any trigger in the chain sets off an infinite loop, the nesting level is exceeded and the trigger is canceled. When a [!INCLUDE[tsql](../../includes/tsql-md.md)] trigger executes managed code by referencing a CLR routine, type, or aggregate, this reference counts as one level against the 32-level nesting limit. Methods invoked from within managed code do not count against this limit
390404

391-
To disable nested triggers, set the nested triggers option of sp_configure to 0 (off). The default configuration allows for nested triggers. If nested triggers is off, recursive triggers is also disabled, regardless of the RECURSIVE_TRIGGERS setting set by using ALTER DATABASE.
405+
To disable nested triggers, set the nested triggers option of sp_configure to 0 (off). The default configuration allows for nested triggers. If nested triggers are off, recursive triggers are also disabled, regardless of the RECURSIVE_TRIGGERS setting set by using ALTER DATABASE.
392406

393407
The first AFTER trigger nested inside an INSTEAD OF trigger fires even if the **nested triggers** server configuration option is set to 0. However, under this setting, later AFTER triggers do not fire. We recommend that you review your applications for nested triggers to determine whether the applications comply with your business rules with regard to this behavior when the **nested triggers** server configuration option is set to 0, and then make appropriate modifications.
394408

@@ -405,7 +419,7 @@ SELECT * FROM deleted;
405419
### A. Using a DML trigger with a reminder message
406420
The following DML trigger prints a message to the client when anyone tries to add or change data in the `Customer` table in the [!INCLUDE[ssSampleDBnormal](../../includes/sssampledbnormal-md.md)] database.
407421

408-
```
422+
```sql
409423
CREATE TRIGGER reminder1
410424
ON Sales.Customer
411425
AFTER INSERT, UPDATE
@@ -416,7 +430,7 @@ GO
416430
### B. Using a DML trigger with a reminder e-mail message
417431
The following example sends an e-mail message to a specified person (`MaryM`) when the `Customer` table changes.
418432

419-
```
433+
```sql
420434
CREATE TRIGGER reminder2
421435
ON Sales.Customer
422436
AFTER INSERT, UPDATE, DELETE
@@ -434,13 +448,15 @@ GO
434448

435449
The following example creates a DML trigger in the AdventureWorks2012 database. This trigger checks to make sure the credit rating for the vendor is good (not 5) when an attempt is made to insert a new purchase order into the `PurchaseOrderHeader` table. To obtain the credit rating of the vendor, the `Vendor` table must be referenced. If the credit rating is too low, a message is displayed and the insertion does not execute.
436450

437-
```
451+
```sql
438452
-- This trigger prevents a row from being inserted in the Purchasing.PurchaseOrderHeader
439453
-- table when the credit rating of the specified vendor is set to 5 (below average).
440454

441455
CREATE TRIGGER Purchasing.LowCredit ON Purchasing.PurchaseOrderHeader
442456
AFTER INSERT
443457
AS
458+
IF (@@ROWCOUNT_BIG = 0)
459+
RETURN;
444460
IF EXISTS (SELECT *
445461
FROM Purchasing.PurchaseOrderHeader AS p
446462
JOIN inserted AS i
@@ -481,11 +497,13 @@ GO
481497
### D. Using a database-scoped DDL trigger
482498
The following example uses a DDL trigger to prevent any synonym in a database from being dropped.
483499

484-
```
500+
```sql
485501
CREATE TRIGGER safety
486502
ON DATABASE
487503
FOR DROP_SYNONYM
488504
AS
505+
IF (@@ROWCOUNT = 0)
506+
RETURN;
489507
RAISERROR ('You must disable Trigger "safety" to drop synonyms!',10, 1)
490508
ROLLBACK
491509
GO
@@ -499,7 +517,7 @@ GO
499517

500518
**Applies to**: [!INCLUDE[ssKatmai](../../includes/sskatmai-md.md)] through [!INCLUDE[ssCurrent](../../includes/sscurrent-md.md)].
501519

502-
```
520+
```sql
503521
CREATE TRIGGER ddl_trig_database
504522
ON ALL SERVER
505523
FOR CREATE_DATABASE
@@ -517,7 +535,7 @@ GO
517535

518536
**Applies to**: [!INCLUDE[ssKatmai](../../includes/sskatmai-md.md)] through [!INCLUDE[ssCurrent](../../includes/sscurrent-md.md)].
519537

520-
```
538+
```sql
521539
USE master;
522540
GO
523541
CREATE LOGIN login_test WITH PASSWORD = '3KHJ6dhx(0xVYsdf' MUST_CHANGE,
@@ -542,14 +560,16 @@ END;
542560
### G. Viewing the events that cause a trigger to fire
543561
The following example queries the `sys.triggers` and `sys.trigger_events` catalog views to determine which [!INCLUDE[tsql](../../includes/tsql-md.md)] language events cause trigger `safety` to fire. `safety` is created in the previous example.
544562

545-
```
563+
```sql
546564
SELECT TE.*
547565
FROM sys.trigger_events AS TE
548566
JOIN sys.triggers AS T ON T.object_id = TE.object_id
549567
WHERE T.parent_class = 0 AND T.name = 'safety';
550568
GO
551569
```
552-
570+
571+
572+
553573
## See Also
554574
[ALTER TABLE &#40;Transact-SQL&#41;](../../t-sql/statements/alter-table-transact-sql.md)
555575
[ALTER TRIGGER &#40;Transact-SQL&#41;](../../t-sql/statements/alter-trigger-transact-sql.md)

0 commit comments

Comments
 (0)