|
YOUR FEEDBACK
|
TOP MICROSOFT .NET LINKS SQL Server 2005 T-SQL Grows Up
Understand the new language features in T-SQL 2005
By: Jerry Dixon
Dec. 23, 2005 01:45 PM
Have you ever heard the expression "I want it so bad that I can taste it?" Well, that's the way I feel about SQL Server 2005. I've been looking forward to the official release for quite some time. When people ask me why, I usually say "SELECT TOP X." In addition to generating some funny looks, this response gets my point across rather nicely. The next version of SQL Server supports many enhancements to the T-SQL language, and the ability to pass a variable to the TOP clause is just one of them. While changes such as this may seem small and insignificant, they can have a large impact on SQL developers.
TOP X In previous versions of T-SQL, the TOP clause could not accept an expression. The number of rows to return had to be stated explicitly. Sometimes, this could be a problem. The code in Listing 2 demonstrates how to select the first seven rows from the Employee table. The result set can be seen in Figure 1. In many situations, it is not possible to determine ahead of time exactly how many rows should be returned. Because the TOP clause could not accept an expression, developers had to resort to dynamic SQL statements such as the one shown in Listing 3. While dynamic SQL statements are not necessarily bad, using them just so that the TOP clause could return different numbers of rows was not optimal. Because the TOP clause can now accept an expression, dynamic SQL is no longer necessary. A developer can use code similar to that in Listing 4 to return a variable number of rows. The code in both Listing 3 and Listing 4 returns the same results (Figure 1), but the code in Listing 4 is more efficient and less prone to errors. Wrap the code in a stored procedure, pass in the number of required rows via a parameter, and you can save the dynamic SQL for other uses.
Structured Error Handling The new TRY-CATCH construct, shown in Listing 5, addresses this. Any number of SQL statements can be placed between matching BEGIN TRY and END TRY statements. This is followed by matching BEGIN CATCH and END CATCH statements, which contain error-handling code. If an error is generated by the code inside the TRY block, the code in the CATCH block is executed. If no error is generated, the code in the CATCH block is bypassed. As you might expect, TRY-CATCH constructs can be nested. The TRY or the CATCH blocks, or both, can contain additional TRY-CATCH constructs. In addition, there are a few T-SQL functions that work only from within a CATCH block. These functions are summarized in Table 1. In Listing 6, we see an example taken from the SQL 2005 Books Online. The code attempts to delete a row from the Product table, which belongs to the Production schema. This will not succeed, and instead causes a constraint violation. When this error occurs, the code in the CATCH block will execute, which returns useful error information to the caller. The result set is shown in Figure 2. This programming paradigm is vastly superior to that allowed by previous versions of SQL Server.
Common Table Expressions To create a CTE, you must use the new WITH statement (see Listing 7 for the syntax). In Listing 8, a simple, nonrecursive CTE has been created. It consists of a single SELECT statement that returns three columns from the Employee table. Because the WITH statement does not specify any column names, the names defined in the SELECT statement will be used. Therefore, this CTE creates a result set that contains three columns from the Employee table, and assigns it the name "Employee." (If a CTE uses the same name as a table, the CTE name takes precedence in subsequent queries.) To use the CTE, all you have to do is refer to it in a query. The SELECT statement below this CTE returns the entire contents of the CTE's result set, which is shown in Figure 3. As useful as this is, we can do better. In Listing 9, the WITH statement includes names for the columns in the result set. Notice that the number of names matches the number of columns in the embedded SELECT statement. The query also includes a GROUP BY clause and the COUNT aggregate function. The result set, shown in Figure 4, lists the occurrences of Married versus Unmarried employees broken down by Gender. In Listing 10, a single CTE is used twice in the subsequent query. The results of this query, shown in Figure 5, compare each employee's total sales figures to that of their managers. As you can see, these capabilities can be used to make complex SQL batches more readable. You should remember, however, that they typically exhibit comparable performance to queries written without CTEs. Now comes the good part. Remember that CTEs can refer to themselves, thus allowing recursive SQL statements to be created. This capability is very useful when you store hierarchical data in an SQL table. Retrieving this data is most easily accomplished via a recursive SELECT statement. However, this was not possible in earlier versions of SQL Server. Developers were reduced to creating recursive stored procedures or more complex WHILE loops. Now with CTEs, we can easily use recursion to simply the process. Suppose that we create a table to store employee information. Each row of the table contains an Employee ID, pertinent employee information, and a Manager ID. (This is actually the case in the SQL Server 2005 AdventureWorks database.) The Manager ID contains the Employee ID of the employee's manager. This hierarchy can be arbitrarily deep. In Listing 11, we see a recursive CTE that retrieves data from this table. The first thing that you will notice is that this CTE contains two SELECT statements joined together with a UNION ALL clause. Although multiple statements can be used in a nonrecursive query, they are required in a recursive one. The first SELECT statement handles the "anchor" or terminating condition. This statement returns those employees at the top of the hierarchy and who therefore have no managers. The second statement handles the recurring condition, returning those employees that do have managers. Notice that this second statement contains an INNER JOIN between the Employee table and the CTE itself. This is what makes the CTE recursive. Figure 6 shows the result set, which lists the manager ID for each employee.
Summary MICROSOFT .NET LATEST STORIES
SUBSCRIBE TO THE WORLD'S MOST POWERFUL NEWSLETTERS SUBSCRIBE TO OUR RSS FEEDS & GET YOUR SYS-CON NEWS LIVE!
|
SYS-CON FEATURED WHITEPAPERS MOST READ THIS WEEK BREAKING NEWS FROM THE WIRES
|
|||||||||||||||||||||||||||||||||||