+ All Categories
Home > Documents > Top 10 Advanced Features of SQL Server 2005

Top 10 Advanced Features of SQL Server 2005

Date post: 13-Nov-2014
Category:
Upload: santosh-kumar
View: 105 times
Download: 1 times
Share this document with a friend
28
Top 10 advanced features of SQL Server 2005 Takeaway: SQL Server 2005 offers new features that enhance productivity, efficiency, availability, and administrative ease. Tim Chapman discusses 10 of the more advanced new features of the SQL Server 2005 Database Engine. SQL Server 2005 offers a plethora of new features and enhancements that improve productivity, efficiency, availability, and administrative ease. In this article, I discuss 10 of the more advanced features of the SQL Server 2005 Database Engine. 1. Database mirroring Database mirroring is a new high-availability feature in SQL Server 2005. It's similar to server clustering in that failover is achieved by the use of a stand-by server; the difference is that the failover is at the database level rather than the server level. The primary database continuously sends transaction logs to the backup database on a separate SQL Server instance. A third SQL Server instance is then used as a witness database to monitor the interaction between the primary and the mirror databases. 2. Database snapshots A database snapshot is essentially an instant read-only copy of a database, and it is a great candidate for any type of reporting solution for your company. In addition to being a great reporting tool, you can revert control from your primary database to your snapshot database in the event of an error. The only data loss would be from the point of creation of the database snapshot to the event of failure.
Transcript

Top 10 advanced features of SQL Server 2005

Takeaway: SQL Server 2005 offers new features that enhance productivity, efficiency, availability, and administrative ease. Tim Chapman discusses 10 of the more advanced new features of the SQL Server 2005 Database Engine.

SQL Server 2005 offers a plethora of new features and enhancements that improve productivity, efficiency, availability, and administrative ease. In this article, I discuss 10 of the more advanced features of the SQL Server 2005 Database Engine.

1. Database mirroring

Database mirroring is a new high-availability feature in SQL Server 2005. It's similar to server clustering in that failover is achieved by the use of a stand-by server; the difference is that the failover is at the database level rather than the server level. The primary database continuously sends transaction logs to the backup database on a separate SQL Server instance. A third SQL Server instance is then used as a witness database to monitor the interaction between the primary and the mirror databases.

2. Database snapshots

A database snapshot is essentially an instant read-only copy of a database, and it is a great candidate for any type of reporting solution for your company. In addition to being a great reporting tool, you can revert control from your primary database to your snapshot database in the event of an error. The only data loss would be from the point of creation of the database snapshot to the event of failure.

3. CLR integration

With SQL Server 2005, you now have the ability to create custom .NET objects with the database engine. For example, stored procedures, triggers, and functions can now be created using familiar .NET languages such as VB and C#. Exposing this functionality gives you tools that you never had access to before such as regular expressions.

Weekly SQL tips in your inboxTechRepublic's free SQL Server newsletter, delivered each Tuesday, contains hands-on tips that will help you become more adept with this powerful relational database management system.

4. Service Broker

This feature gives you the ability to create asynchronous, message-based applications in the database entirely through TSQL. The database engine guarantees message delivery,

message order consistency, and handles message grouping. In addition, Service Broker gives you the ability to send messages between different SQL Server instances. Server Broker is also used in several other features in SQL Server 2005. For example, you can define Event Nonfictions in the database to send a message to a Queue in the database when someone attempts to alter a table structure, of if there is a string of login failures.

5. DDL triggers

In previous articles, I outlined how you can use data definition language (DDL) triggers in SQL Server 2005 to implement custom database and server auditing solutions for Sarbanes-Oxley compliance (here are part one and part two of my SOX articles). DDL triggers are defined at the server or database level and fire when DDL statements occur. This gives you the ability to audit when new tables, stored procedures, or logins are created.

6. Ranking functions

SQL Server 2005 provides you with the ability to rank result sets returned from the database engine. This allows you to customize the manner in which result sets are returned, such as creating customized paging functions for Web site data.

7. Row versioning-based isolation levels

This new database engine feature improves database read concurrency by reducing the amount of locks being used in your database. There are two versions of this feature (both of which must be enabled at the database level):

Read Committed Isolation Using Row Versioning is used at the individual statement level, and guarantees that the data is consistent for the duration of the statement.

Snapshot Isolation is used at the transaction level, and guarantees that the data is consistent for the duration of the transaction.

The database engine is able to guarantee the consistency through row versions stored in the tempdb database. When a statement or transaction is issued with their respective isolation levels, read operations accessing the same data that is being involved in a transaction will read from the previous version of the data that is stored in tempdb. Using these techniques in the appropriate situations can significantly decrease your database locking issues.

8. XML integration

SQL Server 2005 introduces the new XML data-type. You can store full XML documents in this new data-type, and you can place validations on the well-formed documents in the database. Additional enhancements include the ability to query the XML documents and create indexes on the XML data-type.

9. TRY...CATCH

In a previous article, I outlined how you can use the new TRY...CATCH constructs in SQL Server 2005 to catch and handle deadlocks when they occur in the database. This long-awaited feature simplifies error handling in the database.

10. Database Mail

Database Mail, the eventual successor to SQL Mail, is a greatly enhanced e-mail solution available in the database engine. With Database Mail, there is no longer a dependency on Microsoft Outlook or MAPI e-mail clients. Database Mail uses standard SMTP to send e-mail messages. These messages may contain query results, attachments (which can be governed by the DBA), and is fully cluster aware. In addition, the e-mail process runs outside of the database engine space, which means that messages can continue to be queued even when the database engine has stopped.

What are your favorite features?

If you are using SQL Server 2005, I would love to hear about your favorite features. Please post your comments in the article discussion.

Understanding the new Try/Catch statement in SQL Server 2005Versions prior to SQL Server 2005 offered little in the way of error handling—Raiserror() was about it. SQL Server 2005 adds the Try/Catch statement, which is modeled on the similar construct in Java and other development languages.

Try/Catch consists of two blocks—Try and Catch—each of which can contain multiple statements. Listing A contains a simple example in pseudo-code.

If either the insert or the update fails, the implicit transaction is rolled back. The insert statement cannot succeed (i.e., it is committed) while the update statement fails. Both succeed or both fail.

(Note: Any error that is caught by the Catch block is not returned to the caller.)

With SQL Server 2000, any fatal error (i.e., an error with a severity level greater than 17) immediately terminates execution and breaks the connection. With SQL Server 2005, the engine will attempt to handle the error and continue execution. Listing B illustrates this point.

When you paste the code from Listing B into a new query window in Management Studio and execute it, the results look like this:

Begin Try

Begin Catch

Variable @int = 0

Code Completed

The Try block attempts to divide by zero, which immediately invokes the Catch block; this prints its message and then assigns zero to the variable. Code execution continues, printing the final two statements.

Using built-in functions in the Catch block

Six new functions are available in SQL Server 2005 for use within the Catch block. Here are brief descriptions of each of the functions:

Error_Message(): returns the error message that would typically be sent to the caller.

Error_Number(): returns the integer assigned to the error. Error_Severity(): returns the integer corresponding to the severity. Error_State(): returns the state. Error_Procedure(): returns the name of the procedure or function where the

error occurred. Error_Line(): returns the line number where the error occurred.

To demonstrate the functions' use, I revised the code, which you can see in Listing C.

I fancied up the custom error message so it displays on multiple lines for clarity. (You might want to keep this code for use as a template Catch block in the future.) This results in the following display:

Begin Try

Begin CatchMsg 50000, Level 16, State 2, Line 20 Error(8134): Divide by zero error encountered. Severity: 16 State:    1 Procedure: None.

 Line #:    4

Variable @int = 0

Code Completed

Note: Application code would typically be using transactions. The mere existence of a Catch block won't automatically perform a rollback—you must do it yourself. In this case, your procedure would resemble this generic version:

BEGIN TRY    BEGIN TRANSACTION    [Do some stuff here]    COMMIT TRANSACTION

END TRY

BEGIN CATCH    Print 'Begin Catch'    ROLLBACK TRANSACTION    [Do some stuff here]

END CATCH

Error handling has come a long way in SQL Server 2005. If you're still handling errors the old way, with nothing more than Raiserror() in your toolkit, it's time to wake up and smell the coffee!

Miss a tip?

Check out the SQL Server archive, and catch up on the most recent editions of Arthur Fuller's column.

TechRepublic's free SQL Server newsletter, delivered each Tuesday, contains hands-on tips that will help you become more adept with this powerful relational database management system. Automatically subscribe today!

Understanding error handling in SQL Server 2000

Most iterative language compilers have built-in error handling routines (e.g., TRY…CATCH statements) that developers can leverage when designing their code. Although SQL Server 2000 developers don't enjoy the luxury that iterative language developers do when it comes to built-in tools, they can use the @@ERROR system variable to design their own effective error-handling tools.

Introducing transactions

In order to grasp how error handling works in SQL Server 2000, you must first understand the concept of a database transaction. In database terms, a transaction is a series of statements that occur as a single unit of work. To illustrate, suppose you have three statements that you need to execute. The transaction can be designed in such a way so that all three statements occur successfully, or none of them occur at all.

When data manipulation operations are performed in SQL Server, the operation takes place in buffer memory and not immediately to the physical table. Later, when the CHECKPOINT process is run by SQL Server, the committed changes are written to disk. This means that when transactions are occurring, the changes are not made to disk during the transaction, and are never written to disk until committed. Long-running transactions require more processing memory and require that the database hold locks for a longer period of time. Thus, you must be careful when designing long running transactions in a production environment.

Here's a good example of how using transactions is useful. Withdrawing money from an ATM requires a series of steps which include entering a PIN number, selecting an account type, and entering the amount of funds you wish to withdraw. If you try to withdraw $50 from the ATM and the machine fails thereafter, you do not want to be charged the $50 without receiving the money. Transactions can be used to ensure this consistency.

The @@ERROR variable

Successful error handling in SQL Server 2000 requires consistently checking the value of the @@ERROR system variable. @@ERROR is a variable updated by the SQL Server database engine after each statement is executed on the server for the given connection. This variable contains the corresponding error number, if applicable. You can find a listing of these error numbers in the sysmessages table in the master database. The details of this table are listed on Microsoft's site.

Here's an example of how the @@ERROR variable works:

PRINT 'Taking a look at @@ERROR'

PRINT @@ERROR

In these instructions, we are printing out a string to the screen and printing the value of the @@ERROR variable. Because no error is returned from printing out to the screen, the value @@ERROR contains is 0.

PRINT 1/0

PRINT @@ERROR

In this example, we generate a division by zero error, which means that the @@ERROR variable will contain 8134, which is the error number that Microsoft assigns for this type of error. For most error handling purposes, you will only be concerned if the value of @@ERROR is non-zero, which will indicate that an error occurred. It is a good idea to keep track of the error numbers when recording the errors as they will come in handy during the debugging process.

Error handling at work

Here's a good example of how you can use error handling in stored procedures. The goal of the sample script is to execute a stored procedure that will declare a transaction and insert a record into a table. Because this is for explanation purposes only, we will design the procedure in such a way as to let us tell it whether to commit or roll back the transaction.

Execute the following statement to create the table that we will use for our example:

CREATE TABLE Transactions

(      TranID SMALLINT IDENTITY(1,1) PRIMARY KEY,      EntryDate SMALLDATETIME DEFAULT(GETDATE()),      ParamValue CHAR(1),       ThrowError BIT

)

The two fields of value in the script are ParamValue and ThrowError. These fields will correspond to the input parameters of the procedure we will create, and we will use them in our logic for committing transactions.

Once our table is in place to keep track of our transactions, we are ready to create our procedure. The procedure will have a parameter used simply to record a character value and a parameter, which will give us the ability to throw an error in the procedure. Run the statement in Listing A to create the procedure.

This simple stored procedure exhibits the characteristics we need for effective error handling. First, a transaction is explicitly declared. After a record is inserted into the Transaction table, we check the value of the @ThrowError parameter. This parameter indicates whether to throw an error, and uses the RAISERROR function to throw the custom error. When the RAISERROR function is called, the value of the @@ERROR variable is populated with the error number that we provide.

If an error occurs in the stored procedure, we will roll back the transaction. Rolling back the transactions means that the record we attempted to insert into the Transactions table will be removed as if it never occurred. The state of the database will be exactly how it was before the transaction began.

In this example, you will also notice the use of the GOTO statement and the label ErrorHandler. GOTO statements are typically considered a bad programming practice in iterative programming languages, but they are very useful when handling errors in SQL Server 2000. Don't be afraid to use the GOTO statement to handle errors.

This procedure call will throw an error and the record will not be inserted in the Transactions table:

DECLARE @ReturnCode INT

EXECUTE @ReturnCode = usp_TestTransaction @ParamValue = 'E', @ThrowError = 1

PRINT @ReturnCode

This procedure call will not throw an error, and the inserted record will be committed to the Transactions table:

DECLARE @ReturnCode INT

EXECUTE @ReturnCode = usp_TestTransaction @ParamValue = 'S', @ThrowError = 0

PRINT @ReturnCode

These procedure calls make use of a Return parameter, which indicates the success or failure of a stored procedure. It is a good programming practice to explicitly set the Return parameter in your code to indicate success or failure of the procedure; this allows you to know when your stored procedure has failed so you can take the necessary steps to handle the failure. For example, you can nest procedure calls and transactions. Your application could potentially declare a transaction, call a stored procedure, and (depending on the success or failure of the stored procedure) commit or roll back the outside transaction.

Looking to the future

Careful transaction design and consistently checking the value of the @@ERROR variable is the key to effective error handling in SQL Server 2000. In a future article, I'll show you how to use the new error handling capabilities in SQL Server 2005, which

T-SQL error handling with Try…Catch blocks

SQL Server error handling, or exception handling, has always been a tricky part of T-SQL development. It used to be that you had to manually check for errors after running each statement and handle them on a case-by-case basis. SQL Server transaction management was also a chore because you had to figure out the state of your transactions and roll them back or commit them as appropriate.

With SQL Server 2005, Microsoft gives us newer, more robust error handling capabilities by adding Try...Catch blocks to T-SQL. In this tip, we will look at how Try...Catch blocks work and how you can put them to use in your code. We will also look at some comparisons between the old ways and the new ways so you'll have a better understanding of how using Try...Catch can bring your error handling into the 21st century.

Try...Catch defined

In order to understand Try…Catch blocks, you have to understand exception handling. Exception handling is simple really: When something unplanned occurs during

the execution of your code, an exception, you need to have a routine that can handle that exception. How you handle the exception is up to you as the developer.

In order to add exception handling to your T-SQL code, you use Try…Catch blocks. If you have used Visual Studio recently, you are probably familiar with the concept of Try…Catch blocks. Their implementation in T-SQL is similar but actually has fewer options than the full-blown implementation you would encounter in Visual Studio. To use Try…Catch, put the T-SQL code

you want to run inside of a Try block. If an error with a severity of 10 or higher occurs during the execution of the Try code, execution is passed to exception handling code in a Catch block. The basic construct is shown below:

BEGIN TRY [T-SQL Code Goes Here]END TRYBEGIN CATCH [Exception Handling Code Goes Here]END CATCH

When using Try…Catch in T-SQL, here are a few crucial points to keep in mind:

Try blocks must be followed directly by a Catch block, anything else will cause an error. Try…Catch cannot span batches. If the Try code runs without fail, execution passes to the first line following the end of the Catch block.

More on T-SQL and SQL Server performance tuning:

Top 10 T-SQL tips for improved SQL Server development Guide: SQL Server 2005 performance tuning tools A-Z

When Catch code completes, execution passes to the first line following the end of the Catch block.

Handling errors

When an error occurs, you as the developer need to decide how to deal with it. Since you cannot pass control back to code that caused the error, like you can in .NET languages, you will likely log the problem and roll back any transactions that may be in-flight. To help with logging, there are several system functions that can provide more information about an error. The available system functions are detailed below:

ERROR_NUMBER() - Returns the error number. ERROR_SEVERITY() - Returns the error's severity. ERROR_STATE() - Returns the error's state. ERROR_PROCEDURE() - Returns the name of the stored procedure or trigger in which the error occurred. ERROR_LINE() - Returns the line number on which the error occurred. ERROR_MESSAGE() returns the actual text of the error message.

Using these functions, you can record the details of the error and return that information to the caller of the procedure or log it for troubleshooting purposes. The functions will only work when called inside a Catch block; trying to call them otherwise would return NULL. They will, however, work within the scope of the code running in the Catch block. This means that you can call a stored procedure to handle the error and that stored procedure can access the error functions. Here is an example of just such a stored procedure:

CREATE PROCEDURE spLogErrorAS

--Return error details to calling applicationSELECT ERROR_NUMBER() AS ErrNum, ERROR_SEVERITY() AS ErrSev, ERROR_STATE() as ErrState, ERROR_PROCEDURE() as ErrProc, ERROR_LINE() as ErrLine, ERROR_MESSAGE() as ErrMsg

--Log error to error databasesINSERT INTO SQLErrors.dbo.ErrorLogVALUES(ERROR_NUMBER(), ERROR_SEVERITY(), ERROR_STATE(), ERROR_PROCEDURE(), ERROR_LINE(),ERROR_MESSAGE())

This procedure can then be called in your Catch block to return and log the error details.

BEGIN TRY--INSERT CODE HERE: When an error occurs, control will be passed to the Catch block END TRY

BEGIN CATCH--This proc will log the error and send the details back to the calling applicationEXEC spLogErrorEND CATCH

Using the XACT_STATE() function

There is one more error function that we have not discussed, the XACT_STATE() function. This function can be called in your Catch blocks to return the exact transaction state of your procedure. The return code from XACT_STATE() will have one of the following values:

1 : There is an active transaction that could be either committed or rolled back. 0 : There is no active transaction. -1 : There is an active transaction, but errors have occurred and the transaction cannot be committed.

Based on the return of this function, you can handle your in-flight transaction. If you receive a 1, you can roll back or commit as normal. If you receive a 0, there are no open transactions, and attempting a commit would generate an error. The special case is -1. That means there was a transaction, but it is not committable. You are also unable to roll back to a save point when you receive a -1 code; the entire transaction must be rolled back.

Error and exception handling is crucial to any good coding standards. Now with SQL Server 2005 you can implement advanced error handling using Try…Catch blocks.

TRY...CATCH (Transact-SQL)

Updated: 14 April 2006

Implements error handling for Transact-SQL that is similar to the exception handling in the Microsoft

Visual C# and Microsoft Visual C++ languages. A group of Transact-SQL statements can be enclosed

in a TRY block. If an error occurs in the TRY block, control is passed to another group of statements

that is enclosed in a CATCH block.

 Syntax

BEGIN TRY

     { sql_statement | statement_block }

END TRY

BEGIN CATCH

          [ { sql_statement | statement_block } ]

END CATCH

[ ; ]

 Arguments

sql_statement

Is any Transact-SQL statement.

statement_block

Any group of Transact-SQL statements in a batch or enclosed in a BEGIN…END block.

 Remarks

A TRY…CATCH construct catches all execution errors that have a severity higher than 10 that do not

close the database connection.

A TRY block must be immediately followed by an associated CATCH block. Including any other

statements between the END TRY and BEGIN CATCH statements generates a syntax error.

A TRY…CATCH construct cannot span multiple batches. A TRY…CATCH construct cannot span

multiple blocks of Transact-SQL statements. For example, a TRY…CATCH construct cannot span two

BEGIN…END blocks of Transact-SQL statements and cannot span an IF…ELSE construct.

If there are no errors in the code that is enclosed in a TRY block, when the last statement in the TRY

block has finished running, control passes to the statement immediately after the associated END

CATCH statement. If there is an error in the code that is enclosed in a TRY block, control passes to

the first statement in the associated CATCH block. If the END CATCH statement is the last statement

in a stored procedure or trigger, control is passed back to the statement that called the stored

procedure or fired the trigger.

When the code in the CATCH block finishes, control passes to the statement immediately after the

END CATCH statement. Errors trapped by a CATCH block are not returned to the calling application.

If any part of the error information must be returned to the application, the code in the CATCH block

must do so by using mechanisms such as SELECT result sets or the RAISERROR and PRINT

statements. For more information about how to use RAISERROR with TRY…CATCH, see Using

TRY...CATCH in Transact-SQL.

TRY…CATCH constructs can be nested. Either a TRY block or a CATCH block can contain nested

TRY…CATCH constructs. For example, a CATCH block can contain an embedded TRY…CATCH

construct to handle errors encountered by the CATCH code.

Errors encountered in a CATCH block are treated like errors generated anywhere else. If the CATCH

block contains a nested TRY…CATCH construct, any error in the nested TRY block will pass control to

the nested CATCH block. If there is no nested TRY…CATCH construct, the error is passed back to the

caller.

TRY…CATCH constructs catch unhandled errors from stored procedures or triggers executed by the

code in the TRY block. Alternatively, the stored procedures or triggers can contain their own TRY…

CATCH constructs to handle errors generated by their code. For example, when a TRY block

executes a stored procedure and an error occurs in the stored procedure, the error can be handled

in the following ways:

If the stored procedure does not contain its own TRY…CATCH construct, the error returns

control to the CATCH block associated with the TRY block that contains the EXECUTE

statement.

If the stored procedure contains a TRY…CATCH construct, the error transfers control to the

CATCH block in the stored procedure. When the CATCH block code finishes, control is

passed back to the statement immediately after the EXECUTE statement that called the

stored procedure.

GOTO statements cannot be used to enter a TRY or CATCH block. GOTO statements can be used to

jump to a label inside the same TRY or CATCH block or to leave a TRY or CATCH block.

The TRY…CATCH construct cannot be used in a user-defined function.

Retrieving Error Information

In the scope of a CATCH block, the following system functions can be used to obtain information

about the error that caused the CATCH block to be executed:

ERROR_NUMBER() returns the number of the error.

ERROR_SEVERITY() returns the severity.

ERROR_STATE() returns the error state number.

ERROR_PROCEDURE() returns the name of the stored procedure or trigger where the error

occurred.

ERROR_LINE() returns the line number inside the routine that caused the error.

ERROR_MESSAGE() returns the complete text of the error message. The text includes the

values supplied for any substitutable parameters, such as lengths, object names, or times.

These functions return NULL if they are called outside the scope of the CATCH block. Error

information can be retrieved by using these functions from anywhere within the scope of the CATCH

block. For example, the following script shows a stored procedure that contains error-handling

functions. In the CATCH block of a TRY…CATCH construct, the stored procedure is called and

information about the error is returned.

Copy Code

USE AdventureWorks;

GO

-- Verify that the stored procedure does not already exist.

IF OBJECT_ID ( 'usp_GetErrorInfo', 'P' ) IS NOT NULL

DROP PROCEDURE usp_GetErrorInfo;

GO

-- Create procedure to retrieve error information.

CREATE PROCEDURE usp_GetErrorInfo

AS

SELECT

ERROR_NUMBER() AS ErrorNumber,

ERROR_SEVERITY() AS ErrorSeverity,

ERROR_STATE() AS ErrorState,

ERROR_PROCEDURE() AS ErrorProcedure,

ERROR_LINE() AS ErrorLine,

ERROR_MESSAGE() AS ErrorMessage;

GO

BEGIN TRY

-- Generate divide-by-zero error.

SELECT 1/0;

END TRY

BEGIN CATCH

-- Execute error retrieval routine.

EXECUTE usp_GetErrorInfo;

END CATCH;

Errors Unaffected by a TRY…CATCH Construct

TRY…CATCH constructs do not trap the following conditions:

Warnings or informational messages that have a severity of 10 or lower.

Errors that have a severity of 20 or higher that stop the SQL Server Database Engine task

processing for the session. If an error occurs that has severity of 20 or higher and the

database connection is not disrupted, TRY…CATCH will handle the error.

Attentions, such as client-interrupt requests or broken client connections.

When the session is ended by a system administrator by using the KILL statement.

The following types of errors are not handled by a CATCH block when they occur at the same level of

execution as the TRY…CATCH construct:

Compile errors, such as syntax errors, that prevent a batch from running.

Errors that occur during statement-level recompilation, such as object name resolution

errors that occur after compilation because of deferred name resolution.

These errors are returned to the level that ran the batch, stored procedure, or trigger.

If an error occurs during compilation or statement-level recompilation at a lower execution level (for

example, when executing sp_executesql or a user-defined stored procedure) inside the TRY block,

the error occurs at a lower level than the TRY…CATCH construct and will be handled by the

associated CATCH block. For more information, see Using TRY...CATCH in Transact-SQL.

The following example shows how an object name resolution error generated by a SELECT

statement is not caught by the TRY…CATCH construct, but is caught by the CATCH block when the

same SELECT statement is executed inside a stored procedure.

Copy Code

USE AdventureWorks;

GO

BEGIN TRY

-- Table does not exist; object name resolution

-- error not caught.

SELECT * FROM NonexistentTable;

END TRY

BEGIN CATCH

SELECT

ERROR_NUMBER() as ErrorNumber,

ERROR_MESSAGE() as ErrorMessage;

END CATCH

The error is not caught and control passes out of the TRY…CATCH construct to the next higher level.

Running the SELECT statement inside a stored procedure will cause the error to occur at a level

lower than the TRY block. The error will be handled by the TRY…CATCH construct.

Copy Code

-- Verify that the stored procedure does not exist.

IF OBJECT_ID ( N'usp_ExampleProc', N'P' ) IS NOT NULL

DROP PROCEDURE usp_ExampleProc;

GO

-- Create a stored procedure that will cause an

-- object resolution error.

CREATE PROCEDURE usp_ExampleProc

AS

SELECT * FROM NonexistentTable;

GO

BEGIN TRY

EXECUTE usp_ExampleProc

END TRY

BEGIN CATCH

SELECT

ERROR_NUMBER() as ErrorNumber,

ERROR_MESSAGE() as ErrorMessage;

END CATCH;

For more information about batches, see Batches.

Uncommittable Transactions and XACT_STATE

If an error generated in a TRY block causes the state of the current transaction to be invalidated, the

transaction is classified as an uncommittable transaction. An error that ordinarily ends a transaction

outside a TRY block causes a transaction to enter an uncommittable state when the error occurs

inside a TRY block. An uncommittable transaction can only perform read operations or a ROLLBACK

TRANSACTION. The transaction cannot execute any Transact-SQL statements that would generate a

write operation or a COMMIT TRANSACTION. The XACT_STATE function returns a value of -1 if a

transaction has been classified as an uncommittable transaction. When a batch finishes, the

Database Engine rolls back any active uncommittable transactions. If no error message was sent

when the transaction entered an uncommittable state, when the batch finishes, an error message

will be sent to the client application. This indicates that an uncommittable transaction was detected

and rolled back.

For more information about uncommittable transactions and the XACT_STATE function, see Using

TRY...CATCH in Transact-SQL and XACT_STATE (Transact-SQL).

 Examples

A. Using TRY…CATCH

The following example shows a SELECT statement that will generate a divide-by-zero error. The

error causes execution to jump to the associated CATCH block.

Copy Code

USE AdventureWorks;

GO

BEGIN TRY

-- Generate a divide-by-zero error.

SELECT 1/0;

END TRY

BEGIN CATCH

SELECT

ERROR_NUMBER() AS ErrorNumber,

ERROR_SEVERITY() AS ErrorSeverity,

ERROR_STATE() AS ErrorState,

ERROR_PROCEDURE() AS ErrorProcedure,

ERROR_LINE() AS ErrorLine,

ERROR_MESSAGE() AS ErrorMessage;

END CATCH;

GO

B. Using TRY…CATCH in a transaction

The following example shows how a TRY…CATCH block works inside a transaction. The statement

inside the TRY block generates a constraint violation error.

Copy Code

USE AdventureWorks;

GO

BEGIN TRANSACTION;

BEGIN TRY

    -- Generate a constraint violation error.

    DELETE FROM Production.Product

        WHERE ProductID = 980;

END TRY

BEGIN CATCH

    SELECT

ERROR_NUMBER() AS ErrorNumber,

        ERROR_SEVERITY() AS ErrorSeverity,

    ERROR_STATE() as ErrorState,

ERROR_PROCEDURE() as ErrorProcedure,

ERROR_LINE() as ErrorLine,

        ERROR_MESSAGE() as ErrorMessage;

IF @@TRANCOUNT > 0

ROLLBACK TRANSACTION;

END CATCH;

IF @@TRANCOUNT > 0

COMMIT TRANSACTION;

GO

C. Using TRY…CATCH with XACT_STATE

The following example shows how to use the TRY…CATCH construct to handle errors that occur

inside a transaction. The XACT_STATE function determines whether the transaction should be

committed or rolled back. In this example, SET XACT_ABORT is ON. This makes the transaction

uncommittable when the constraint violation error occurs.

Copy Code

USE AdventureWorks;

GO

-- Check to see whether this stored procedure exists.

IF OBJECT_ID (N'usp_GetErrorInfo', N'P') IS NOT NULL

DROP PROCEDURE usp_GetErrorInfo;

GO

-- Create procedure to retrieve error information.

CREATE PROCEDURE usp_GetErrorInfo

AS

SELECT

ERROR_NUMBER() AS ErrorNumber,

ERROR_SEVERITY() AS ErrorSeverity,

ERROR_STATE() as ErrorState,

ERROR_LINE () as ErrorLine,

ERROR_PROCEDURE() as ErrorProcedure,

ERROR_MESSAGE() as ErrorMessage;

GO

-- SET XACT_ABORT ON will cause the transaction to be uncommittable

-- when the constraint violation occurs.

SET XACT_ABORT ON;

BEGIN TRY

BEGIN TRANSACTION;

-- A FOREIGN KEY constraint exists on this table. This

-- statement will generate a constraint violation error.

DELETE FROM Production.Product

WHERE ProductID = 980;

-- If the DELETE statement succeeds, commit the transaction.

COMMIT TRANSACTION;

END TRY

BEGIN CATCH

-- Execute error retrieval routine.

EXECUTE usp_GetErrorInfo;

-- Test XACT_STATE:

-- If 1, the transaction is committable.

-- If -1, the transaction is uncommittable and should

-- be rolled back.

-- XACT_STATE = 0 means that there is no transaction and

-- a commit or rollback operation would generate an error.

-- Test whether the transaction is uncommittable.

IF (XACT_STATE()) = -1

BEGIN

PRINT

N'The transaction is in an uncommittable state.' +

'Rolling back transaction.'

ROLLBACK TRANSACTION;

END;

-- Test whether the transaction is committable.

IF (XACT_STATE()) = 1

BEGIN

PRINT

N'The transaction is committable.' +

'Committing transaction.'

COMMIT TRANSACTION;

END;

END CATCH;

GO

SQL Server 2005 Books Online (September 2007)

GOTO (Transact-SQL)Alters the flow of execution to a label. The Transact-SQL statement or statements that follow GOTO

are skipped and processing continues at the label. GOTO statements and labels can be used

anywhere within a procedure, batch, or statement block. GOTO statements can be nested.

Transact-SQL Syntax Conventions

 Syntax

Define the label: 

label :

Alter the execution:

GOTO label

 Arguments

label

Is the point after which processing starts if a GOTO is targeted to that label. Labels must follow

the rules for identifiers. A label can be used as a commenting method whether GOTO is used.

 Remarks

GOTO can exist within conditional control-of-flow statements, statement blocks, or procedures, but it

cannot go to a label outside the batch. GOTO branching can go to a label defined before or after

GOTO.

 Permissions

GOTO permissions default to any valid user.

 Examples

The following example shows how to use GOTO as a branch mechanism.

DECLARE @Counter int;

SET @Counter = 1;

WHILE @Counter < 10

BEGIN

SELECT @Counter

SET @Counter = @Counter + 1

IF @Counter = 4 GOTO Branch_One --Jumps to the first branch.

IF @Counter = 5 GOTO Branch_Two --This will never execute.

END

Branch_One:

SELECT 'Jumping To Branch One.'

GOTO Branch_Three; --This will prevent Branch_Two from executing.

Branch_Two:

SELECT 'Jumping To Branch Two.'

Branch_Three:

SELECT 'Jumping To Branch Three.'


Recommended