Anda di halaman 1dari 5

Nesting Stored Procedures

Stored procedures are nested when one stored procedure calls another. You can nest stored procedures up
to 32 levels. The nesting level increases by one when the called stored procedure begins execution and
decreases by one when the called stored procedure completes execution. Attempting to exceed the
maximum of 32 levels of nesting causes the whole calling stored procedure chain to fail. The current
nesting level for the stored procedures in execution is stored in the @@NESTLEVEL function. Although
the nesting limit is 32 levels, Microsoft® SQL Server™ 2000 has no limit on the number of stored
procedures that can be invoked from a given stored procedure, provided that the subordinate stored
procedures do not invoke other subordinate stored procedures and the maximum nesting level is never
exceeded.
An error in a nested stored procedure is not necessarily fatal to the calling stored procedure. When invoking
stored procedures within stored procedures, use the Transact-SQL RETURN statement to return a return
code and check the return code from the calling stored procedure. In this way, you can specify the behavior
of your stored procedures when errors occur. Stored procedures can even do a nested call to themselves, a
technique known as recursion.

@@NESTLEVEL

Returns the nesting level of the current stored procedure execution (initially 0).

Syntax : @@NESTLEVEL

Return Types : integer

Remarks

Each time a stored procedure calls another stored procedure, the nesting level is incremented. When the
maximum of 32 is exceeded, the transaction is terminated.

Examples

This example creates two procedures: one that calls the other, and one that displays the @@NESTLEVEL
setting of each.
CREATE PROCEDURE innerproc as
select @@NESTLEVEL AS 'Inner Level'
GO

CREATE PROCEDURE outerproc as


select @@NESTLEVEL AS 'Outer Level'
EXEC innerproc
GO

EXECUTE outerproc
GO
Here is the result set:
Outer Level
-----------------
1
Inner Level
-----------------
2

1
Returning Data Using a Return Code

A stored procedure can return an integer value called a return code to indicate the execution status of a
procedure. You specify the return code for a stored procedure using the RETURN statement. As with
OUTPUT parameters, you must save the return code in a variable when the stored procedure is executed to
use the return code value in the calling program. For example, the assignment variable @result of data type
int is used to store the return code from the stored procedure my_proc:
DECLARE @result int
EXECUTE @result = my_proc
Return codes are commonly used in control-of-flow blocks within stored procedures to set the return code
value for each possible error situation. You can use the @@ERROR function after a Transact-SQL
statement to detect if an error occurred during the execution of the statement.

Choosing Rows with the HAVING Clause

The HAVING clause sets conditions on the GROUP BY clause similar to the way WHERE interacts with
SELECT. The WHERE search condition is applied before the grouping operation occurs; the HAVING
search condition is applied after the grouping operation occurs. The HAVING syntax is similar to the
WHERE syntax, except HAVING can contain aggregate functions. HAVING clauses can reference any of
the items that appear in the select list.

This query finds publishers whose year-to-date sales are greater than $40,000:
USE pubs
SELECT pub_id, total = SUM(ytd_sales)
FROM titles
GROUP BY pub_id
HAVING SUM(ytd_sales) > 40000
Here is the result set:
pub_id total
------ -----------
0877 44219

(1 row(s) affected)
To make sure there are at least six books involved in the calculations for each publisher, this example uses
HAVING COUNT(*) > 5 to eliminate the publishers that return totals for fewer than six books:
USE pubs
SELECT pub_id, total = SUM(ytd_sales)
FROM titles
GROUP BY pub_id
HAVING COUNT(*) > 5
Here is the result set:
pub_id total
------ -----------
0877 44219
1389 24941

(2 row(s) affected)

Understanding the correct sequence in which the WHERE, GROUP BY, and HAVING clauses are applied
helps in coding efficient queries:
• The WHERE clause is used to filter the rows that result from the operations specified in the
FROM clause.
• The GROUP BY clause is used to group the output of the WHERE clause.
• The HAVING clause is used to filter rows from the grouped result.

2
For any search conditions that could be applied either before or after the grouping operation, it is more
efficient to specify them in the WHERE clause. This reduces the number of rows that have to be grouped.
The only search conditions that should be specified in the HAVING clause are those search conditions that
must be applied after the grouping operation has been performed.
The Microsoft® SQL Server™ 2000 query optimizer can deal with most of these conditions. If the query
optimizer determines that a HAVING search condition can be applied before the grouping operation, it will
do so. The query optimizer might not be able to recognize all of the HAVING search conditions that can be
applied before the grouping operation. It is recommended that you place all such search conditions in the
WHERE clause instead of the HAVING clause.

The following query shows HAVING with an aggregate function. It groups the rows in the titles table by
type and eliminates the groups that include only one book:
USE pubs
SELECT type
FROM titles
GROUP BY type
HAVING COUNT(*) > 1
Here is the result set:
type
------------------
business
mod_cook
popular_comp
psychology
trad_cook

(5 row(s) affected)

This is an example of a HAVING clause without aggregate functions. It groups the rows in titles by type
and eliminates those types that do not start with the letter p.
USE pubs
SELECT type
FROM titles
GROUP BY type
HAVING type LIKE 'p%'
Here is the result set:
type
------------------
popular_comp
psychology

(2 row(s) affected)

When multiple conditions are included in HAVING, they are combined with AND, OR, or NOT. The
following example shows how to group titles by publisher, including only those publishers with
identification numbers greater than 0800, who have paid more than $15,000 in total advances, and who sell
books for an average of less than $20.
SELECT pub_id, SUM(advance) AS AmountAdvanced,
AVG(price) AS AveragePrice
FROM pubs.dbo.titles
WHERE pub_id > '0800'
GROUP BY pub_id
HAVING SUM(advance) > $15000
AND AVG(price) < $20
ORDER BY can be used to order the output of a GROUP BY clause. This example shows using the
ORDER BY clause to define the order in which the rows from a GROUP BY clause are returned:

3
SELECT pub_id, SUM(advance) AS AmountAdvanced,
AVG(price) AS AveragePrice
FROM pubs.dbo.titles
WHERE pub_id > '0800'
AND price >= $5
GROUP BY pub_id
HAVING SUM(advance) > $15000
AND AVG(price) < $20
ORDER BY pub_id DESC

GROUP BY and ALL

Transact-SQL provides the ALL keyword in the GROUP BY clause. ALL is meaningful only when the
SELECT statement also includes a WHERE clause.
If you use ALL, the query results include all groups produced by the GROUP BY clause, even if some of
the groups have no rows that meet the search conditions. Without ALL, a SELECT statement that includes
GROUP BY does not show groups for which no rows qualify.
Here are examples:
USE pubs
SELECT type, AVG(price)
FROM titles
WHERE royalty = 10
GROUP BY type
Here is the result set:
type
------------ --------------------------
business 17.31
popular_comp 20.00
psychology 14.14
trad_cook 17.97

(4 row(s) affected)

USE pubs
SELECT type, AVG(price)
FROM titles
WHERE royalty = 10
GROUP BY ALL type
Here is the result set:
type
------------ --------------------------
business 17.31
mod_cook (null)
popular_comp 20.00
psychology 14.14
trad_cook 17.97
UNDECIDED (null)

(6 row(s) affected)
The first query produces groups only for those books that commanded royalties of 10 percent. Because no
modern cookbooks have a royalty of 10 percent, there is no group in the results for the mod_cook type.The
second query produces groups for all types, including modern cookbooks and UNDECIDED, even though
the modern cookbook group does not include any rows that meet the qualification specified in the WHERE
clause. The column that holds the aggregate value (the average price) is NULL for groups that lack
qualifying rows.

4
Inserting a Row Using INSERT...Values

The VALUES keyword specifies the values for one row of a table. The values are specified as a comma-
separated list of scalar expressions whose data type, precision, and scale must be the same as or implicitly
convertible to the corresponding column in the column list. If a column list is not specified, the values must
be specified in the same sequence as the columns in the table or view.
For example, this statement inserts a new shipper into the Shippers table using the VALUES clause:
INSERT INTO Northwind.dbo.Shippers (CompanyName, Phone)
VALUES (N'Snowflake Shipping', N'(503)555-7233')
A column list is required for this insert because the ShipperID column has the IDENTITY property;
therefore, values cannot be inserted into it.

Inserting Rows Using INSERT...SELECT

The SELECT subquery in the INSERT statement can be used to add values into a table from one or more
other tables or views. Using a SELECT subquery also lets more than one row be inserted at one time.
This INSERT statement inserts into a separate table some of the data from all the rows in titles whose type
is modern cooking:
USE pubs
INSERT INTO MyBooks
SELECT title_id, title, type
FROM titles
WHERE type = 'mod_cook'
The select list of the subquery must match the column list of the INSERT statement. If no column list is
specified, the select list must match the columns in the table or view being inserted into.
Another use of the INSERT...SELECT statement is to insert data from a source outside of Microsoft® SQL
Server™. The SELECT in the INSERT statement can:

• Reference a remote table on a linked server by using a four-part name.

• Reference a remote table using OPENROWSET.

• Use the result set of a query executed on a remote server.

Inserting Rows Using SELECT INTO

The SELECT INTO statement creates a new table and populates it with the result set of the SELECT. The
structure of the new table is defined by the attributes of the expressions in the select list, for example:
SELECT Shippers.*, Link.Address, Link.City,
Link.Region, Link.PostalCode
INTO NewShippers
FROM Shippers
JOIN LinkServer.DB.dbo.Shippers AS Link
ON (Shippers.ShipperID = Link.ShipperID)

SELECT INTO can be used to combine data from several tables or views into one table. It can also be used
to create a new table containing data selected from a linked server.

Anda mungkin juga menyukai