IT tutorials
 
Database
 

SQL Server 2008 R2 : Using DML Triggers (part 3) - Using inserted and deleted Tables

4/9/2013 9:36:31 PM
- Free product key for windows 10
- Free Product Key for Microsoft office 365
- Malwarebytes Premium 3.7.1 Serial Keys (LifeTime) 2019

3. Using inserted and deleted Tables

In most trigger situations, you need to know what changes were made as part of the data modification. You can find this information in the inserted and deleted tables. For the AFTER trigger, these temporary memory-resident tables contain the rows modified by the statement. With the INSTEAD OF trigger, the inserted and deleted tables are actually temporary tables created on-the-fly.

The inserted and deleted tables have identical column structures and names as the tables that were modified. Consider running the following statement against the BigPubs2008 database:

UPDATE titles
 SET price = $15.05
 WHERE type LIKE '%cook%'

When this statement is executed, a copy of the rows to be modified is recorded, along with a copy of the rows after the modification. These copies are available to the trigger in the deleted and inserted tables.

If you want to be able to see the contents of the deleted and inserted tables for testing purposes, you can create a copy of the table and then create a trigger on that copy (see Listing 2). You can perform data modification statements and view the contents of these tables without the modification actually taking place.

Listing 2. Viewing the Contents of the inserted and deleted Tables
--Create a copy of the titles table in the BigPubs2008 database
SELECT *
 INTO titles_copy
 FROM titles
GO
--add an AFTER trigger to this table for testing purposes
CREATE TRIGGER tc_tr ON titles_copy
 FOR INSERT, UPDATE, DELETE
 AS
 PRINT 'Inserted:'
 SELECT title_id, type, price FROM inserted
 PRINT 'Deleted:'
 SELECT title_id, type, price FROM deleted
  ROLLBACK TRANSACTION

The inserted and deleted tables are available within the trigger after INSERT, UPDATE, and DELETE. Listing 3 shows the contents of inserted and deleted, as reported by the trigger when executing the preceding UPDATE statement.

Listing 3. Viewing the Contents of the inserted and deleted Tables When Updating the titles_copy Table
UPDATE titles_copy
 SET price = $15.05
 WHERE type LIKE '%cook%'

Inserted:
title_id type         price
-------- ------------ ---------------------
TC7777   trad_cook    15.05
TC4203   trad_cook    15.05
TC3218   trad_cook    15.05
MC3021   mod_cook     15.05
MC2222   mod_cook     15.05

Deleted:
title_id type         price
-------- ------------ ---------------------
TC7777   trad_cook    14.3279
TC4203   trad_cook    14.595
TC3218   trad_cook    0.0017
MC3021   mod_cook     15.894
MC2222   mod_cook     14.9532

Note

In SQL Server 2008, an error message is displayed after a rollback is initiated in a trigger. The error message indicates that the transaction ended in the trigger and that the batch has been aborted. Prior to SQL Server 2005, an error message was not displayed when a rollback was encountered in the trigger.


The nature of the inserted and deleted tables enables you to determine the action that fired the trigger. For example, when an INSERT occurs, the deleted table is empty because there were no previous values prior to the insertion. Table 1 shows the DML triggering events and the corresponding contents in the deleted and inserted tables.

Table 1. Determining the Action That Fired a Trigger
StatementContents of insertedContents of deleted
INSERTRows addedEmpty
UPDATENew rowsOld rows
DELETEEmptyRows deleted

Note

Triggers do not fire on a row-by-row basis. One common mistake in coding triggers is to assume that only one row is modified. However, triggers are set-based. If a single statement affects multiple rows in the table, the trigger needs to handle the processing of all the rows that were affected, not just one row at a time.

One common approach to dealing with the multiple rows in a trigger is to place the rows in a cursor and then process each row that was affected, one at a time. This approach works, but it can have an adverse effect on the performance of the trigger. To keep your trigger execution fast, you should try to use rowset-based logic instead of cursors in triggers when possible.

Rowset-based logic will typically join to the inserted or deleted table that are available to a trigger. You can join these tables to other tables that are being manipulated by the trigger. For example, a trigger on a Job table can update a related employee table with rowset-based logic such as :

UPDATE employee
   SET employee.job_lvl = i.min_lvl
  FROM inserted i
 WHERE employee.emp_id = i.emp_id

This kind of logic will allow the trigger update to work correctly if one job record is changed or many job rows are changed at once. This is much more efficient than loading all of the rows from the inserted table into a cursor which updates the employee records one at a time within the cursor loop.


Checking for Column Updates

The UPDATE() function is available inside INSERT and UPDATE triggers. UPDATE() allows a trigger to determine whether a column was affected by the INSERT or UPDATE statement that fired the trigger. By testing whether a column was actually updated, you can avoid performing unnecessary work.

For example, suppose a rule mandates that you cannot change the city for an author (a silly rule, but it demonstrates a few key concepts). Listing 4 creates a trigger for both INSERT and UPDATE that enforces this rule on the authors table in the BigPubs2008 database.

Listing 4. Using the UPDATE() Function in a Trigger
CREATE TRIGGER tr_au_ins_upd ON authors
FOR INSERT, UPDATE
AS
IF UPDATE(city)
 BEGIN
 RAISERROR ('You cannot change the city.', 15, 1)
 ROLLBACK TRAN
 END
GO
UPDATE authors
SET city = city
WHERE au_id = '172-32-1176'

Server: Msg 50000, Level 15, State 1, Procedure
 tr_au_ins_upd, Line 5
 You cannot change the city.

Listing 4 shows how you generally write triggers that verify the integrity of data. If the modification violates an integrity rule, an error message is returned to the client application, and the modification is rolled back.

The UPDATE() function evaluates to TRUE if you update the column in the UPDATE statement. As shown in the preceding example, you do not have to change the value in the column for the UPDATE() function to evaluate to TRUE, but the column must be referenced in the UPDATE statement. For example, with the author update, the city column was set it to itself (the value does not change), but the UPDATE() function still evaluates to TRUE.


Now you can add a couple of INSERT statements on the authors table:

INSERT authors (au_id, au_lname, au_fname, city, contract)
VALUES('111-11-1111', 'White', 'Johnson','Menlo Park', 1)

--Results from the previous insert
Server: Msg 50000, Level 15, State 1
You cannot change the city.

The UPDATE() function evaluates to TRUE and displays the error message. This outcome is expected because the trigger was created for INSERT as well, and the IF UPDATE condition is evaluated for both insertions and updates.

Now you can see what happens if you change the INSERT statement so that it does not include the city column in the INSERT:

INSERT authors (au_id, au_lname, au_fname, contract)
VALUES('111-11-2222', 'White', 'Johnson', 1)

Server: Msg 50000, Level 15, State 1
You cannot change the city.

The error message is still displayed, even though the insertion was performed without the city column. This process might seem counterintuitive, but the IF UPDATE condition always returns a TRUE value for INSERT actions. The reason is that the columns have either explicit default values or implicit (NULL) values inserted, even if they are not specified. The IF UPDATE conditions see this as a change and evaluate to TRUE.

If you change the tr_au_ins_upd trigger to be for UPDATE only (not INSERT and UPDATE), the insertions can take place without error.

 
Others
 
 
 
Top 10
 
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Finding containers and lists in Visio (part 2) - Wireframes,Legends
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Finding containers and lists in Visio (part 1) - Swimlanes
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Formatting and sizing lists
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Adding shapes to lists
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Sizing containers
- Microsoft Access 2010 : Control Properties and Why to Use Them (part 3) - The Other Properties of a Control
- Microsoft Access 2010 : Control Properties and Why to Use Them (part 2) - The Data Properties of a Control
- Microsoft Access 2010 : Control Properties and Why to Use Them (part 1) - The Format Properties of a Control
- Microsoft Access 2010 : Form Properties and Why Should You Use Them - Working with the Properties Window
- Microsoft Visio 2013 : Using the Organization Chart Wizard with new data
Technology FAQ
- Is possible to just to use a wireless router to extend wireless access to wireless access points?
- Ruby - Insert Struct to MySql
- how to find my Symantec pcAnywhere serial number
- About direct X / Open GL issue
- How to determine eclipse version?
- What SAN cert Exchange 2010 for UM, OA?
- How do I populate a SQL Express table from Excel file?
- code for express check out with Paypal.
- Problem with Templated User Control
- ShellExecute SW_HIDE
programming4us programming4us