You are on page 1of 3

Estimated reading time: 5 - 10 minutes

============================================================

Know your DML: The new OUTPUT feature in SQL Server 2005
by Tim Chapman
Published: 5/22/06

Takeaway:
SQL Server 2005's new OUTPUT feature gives developers immediate access to rows
modified by data-manipulation language statements without requiring a separate SELECT
statement against the modified table. Tim Chapman shows you how to take advantage of this
useful new feature.

The ability to immediately access data changes without requiring additional reads from the
database can enhance application throughput. When data modification statements are
executed in SQL Server 2005, you can capture the data that has been modified and store it
for use in subsequent transactions. You can use this technique to prevent the unnecessary
reading of your online transaction processing (OLTP) tables or to implement custom data
auditing without the use of triggers.

A trigger primer
SQL Server 2005 includes two flavors of triggers: data-definition language (DDL) and data-
manipulation language (DML). To learn how to use DDL triggers to create a powerful server
or database auditing solution, see my articles on using SQL Server 2005 to document
Sarbanes-Oxley compliance and creating your own database audit trail. DML triggers are
executed in response to data-manipulation statements and allow you to track any data
change in your database.

How it works
Like DML triggers, the OUTPUT clause makes use of the INSERTED and DELETED tables.
When a data modification statement occurs in the database engine, SQL Server 2005 will
create the INSERTED and DELETED tables and populate them with the data that has been
modified. The structure of these tables will be identical to the table structure for which the
data was altered. For delete statements, only the DELETED table will be populated and
contain the rows that were deleted from the user-defined table. Likewise for insert statements
—only the INSERTED table will be populated. However, for update statements, the
DELETED table will contain the data values prior to the update, and the INSERTED table will
contain pre-update data.

Benefits: In with the OUTPUT
Using the new OUTPUT clause, you can save the altered data to a temporary table or table
variable for later use, eliminating the need to access the original table.
Let's assume that your application uses a transaction composed of three statements that
modify customer data; the database and your company relies upon this application to process
sales information. Due to an abundance of recent sales, performance has degraded. To
illustrate, consider the following sales transaction:

1. Sales are made to five new customers. Information for each customer is added to the
Customers table.
2. For the sales representatives who sold product to these five customers, their
commission figures are updated.
3. Add five new records to your notification system to send thank-you letters to these
customers.

Operations two and three rely upon the information inserted in operation one to accomplish
their tasks. For example, you cannot credit your sales representatives for their new sales
unless you are able to identify the customer to which they have sold product.

Because your sales team has been very successful lately, the Customers table has grown by
200% and is heavily accessed by other enterprise applications. Even if this table is indexed
properly, it is not one you will want to have to read in every transaction your application
requires.

To eliminate unnecessary database reads, use the OUTPUT clause to add these records to a
table variable. In steps two and three, join your tables with this table variable rather than the
Customers table. You can potentially save a tremendous amount of buffer memory and I/O by
using this technique.

Note: Microsoft does not recommended using table variables with large data-sets. If you find
that your application requires using the OUTPUT clause to capture a large amount of data,
use a temporary table instead. Temporary tables live in the tempdb database and allow for
indexing.

Give it a try
In the example above, we looked at the idea of storing records that have been inserted into
the Customers table using the OUTPUT statement and using that data in later transactions.
Run the script in Listing A to set up the data structures we need for our example.

Now that we've created our table structure, we can take a look at how the OUTPUT statement
works. Because table variables reside in SQL Server 2005's memory and are discarded when
the execution context has ended, you'll need to run the script in Listing B at the same time.

Our code declares a table variable and inserts one record into the Customers table. In
addition to the insert statement, we are also using the INSERTED table to add the new record
values into our table variable. At this point, you can use the table variable in place of the
Customers table in steps two and three in our application.

A moment to reflect
The new OUTPUT feature in SQL Server 2005 gives you a lot of new options for designing
applications. The ability to access the data that is being changed without requiring another
database call allows you to optimize your application. As an added benefit, you can use the
OUTPUT clause to create custom auditing without the use of DML triggers.

Listing A

CREATE TABLE Customers

(
CustomerID INT IDENTITY(1,1) PRIMARY KEY,
FirstName VARCHAR(25),
LastName VARCHAR(25),
Address VARCHAR(50),
City VARCHAR(50),
State CHAR(2),
Zip VARCHAR(10),
Age TINYINT
)

GO

Listing B

DECLARE @Customers TABLE

(
CustomerID,
FirstName VARCHAR(25),
LastName VARCHAR(25),
Address VARCHAR(50),
City VARCHAR(50),
State CHAR(2),
Zip VARCHAR(10),
Age TINYINT
)

INSERT INTO Customers

(Firstname, Lastname, Address, City, State, Zip, Age)

OUTPUT

INSERTED.CustomerID, INSERTED.FirstName, INSERTED.LastName,
INSERTED.Address, INSERTED.City, INSERTED.State, INSERTED.Zip, INSERTED.Age

INTO @Customers
(
CustomerID, FirstName, LastName,
Address, City, State, Zip, Age
)

VALUES
('Kyle', 'Wilson', '2000 Elm Street', 'New York', 'CA', '45678-3456', 25)