SQLTeam.com Logo

Return to Introduction to Transactions

Introduction to Transactions

Written by Bill Graziano on 25 January 2004

This article covers the basic of transactions. It describes them and gives examples of committing and rolling back transactions. It also shows how to properly trap errors inside a stored procedure using transactions.

Books Online defines a transaction as a "sequence of operations performed as a single logical unit of work". A transaction has four key properties that are abbreviated ACID. ACID is an acronym for for Atomic Consistent Isolated Durability.

Atomic means that all the work in the transaction is treated as a single unit. Either it is all performed or none of it is. Consistent means that a completed transaction leaves the database in a consistent internal state. Isolations means that the transaction sees the database in a consistent state. This transaction operates on a consistent view of the data. If two transactions try to update the same table, one will go first and then the other will follow. Durability means that the results of the transaction are permanently stored in the system.

The simplest transaction in SQL Server is a single data modification statement. All my examples use the pubs database. The following

UPDATE 	authors
SET	au_fname = 'John'
WHERE	au_id = '172-32-1176'

is a transaction even though it doesn't do much. It's called an Autocommit transaction. SQL Server first writes to the log file what it's going to do. Then it does the actual update statement and finally it writes to the log that it completed the update statement. The writes to the log file are written directly to disk but the update itself is probably done to a copy of the data that resides in memory. At some future point that database will be written to disk. If the server fails after a transaction has been committed and written to the log, SQL Server will use the transaction log to "roll forward" that transaction when it starts up next.

Multi-Statement Transactions

To make transactions a little more usefull you really need to put two or more statements in them. These are called Explicit Transactions. For example,

BEGIN TRAN

UPDATE 	authors
SET	au_fname = 'John'
WHERE	au_id = '172-32-1176'

UPDATE 	authors
SET	au_fname = 'Marg'
WHERE	au_id = '213-46-8915'

COMMIT TRAN

Note that we have a BEGIN TRAN at the beginning and a COMMIT TRAN at the end. These statements start and complete a transaction. Everything inside these statements is considered a logical unit of work. If the system (Note: change statement to system for clarity) fails after the first update, neither update statement will be applied when SQL Server is restarted. The log file will contain a BEGIN TRAN but no corresponding COMMIT TRAN.

Rolling Back

You can also roll back a transaction if it doesn't do what you want. Consider the following transaction:

BEGIN TRAN

UPDATE 	authors
SET	au_fname = 'John'
WHERE	au_id = '172-32-1176'

UPDATE 	authors
SET	au_fname = 'JohnY'
WHERE	city = 'Lawrence'

IF @@ROWCOUNT = 5
  COMMIT TRAN
ELSE
  ROLLBACK TRAN

Suppose that for whatever reason, the second update statement should update exactly five rows. If @@ROWCOUNT, which hold the number of rows affected by each statement, is five then the transaction commits otherwise it rolls back. The ROLLBACK TRAN statement "undoes" all the work since the matching BEGIN TRAN statement. It will not perform either update statement. Note that Query Analyzer will show you messages indicating that rows were updated but you can query the database to verify that no actual data modifications took place.

Stored Procedures

Hopefully most of your transactions will occur in stored procedures. Let's look at the second example inside a stored procedure.

Create Proc TranTest1
AS
BEGIN TRAN

INSERT INTO [authors]([au_id], 
	[au_lname], 
	[au_fname], 
	[phone], 
	[contract])
VALUES	('172-32-1176', 
	'Gates', 
	'Bill', 
	'800-BUY-MSFT', 
	1)

UPDATE 	authors
SET	au_fname = 'Johnzzz'
WHERE	au_id = '172-32-1176'

COMMIT TRAN
GO

The problem with this stored procedure is that transactions don't care if the statements run correctly or not. They only care if SQL Server failed in the middle. If you run this stored procedure, it will try to insert a duplicate entry into the authors database. You'll get a primary key violation error message. The message will even tell you the statment has been terminated. But the transaction is still going. The UPDATE statement runs just fine and SQL Server then commits the transaction. The proper way to code this is:

Create Proc TranTest2
AS
BEGIN TRAN

INSERT INTO [authors]([au_id], 
	[au_lname], 
	[au_fname], 
	[phone], 
	[contract])
VALUES	('172-32-1176', 
	'Gates', 
	'Bill', 
	'800-BUY-MSFT', 
	1)

IF @@ERROR <> 0
   BEGIN
	ROLLBACK TRAN
	return 10
   END

UPDATE 	authors
SET	au_fname = 'Johnzzz'
WHERE	au_id = '172-32-1176'

IF @@ERROR <> 0
   BEGIN
	ROLLBACK TRAN
	return 11
   END

COMMIT TRAN
GO

You'll notice that we check each statement for failure. If the statement failed (i.e. @@ERROR <> 0) then we rollback the work performed so far and use the RETURN statement to exit the stored procedure. It's very important to note that if we don't check for errors after each statement we may commit a transaction improperly.