9767407- Implementing Stored Procedures and Functions

52
Module 7 Implementing Stored Procedures and Functions Contents: Lesson 1: Implementing Stored Procedures 7-2 Lesson 2: Creating Parameterized Stored Procedures 7-10 Lesson 3: Creating Functions 7-18 Lesson 4: Handling Errors 7-28 Lesson 5: Controlling Execution Context 7-36 Lab: Implementing Stored Procedures and Functions 7-44

description

SQL - Implementing Stored Procedures and Functions

Transcript of 9767407- Implementing Stored Procedures and Functions

Page 1: 9767407- Implementing Stored Procedures and Functions

Module 7

Implementing Stored Procedures and Functions

Contents:

Lesson 1: Implementing Stored Procedures 7-2

Lesson 2: Creating Parameterized Stored Procedures 7-10

Lesson 3: Creating Functions 7-18

Lesson 4: Handling Errors 7-28

Lesson 5: Controlling Execution Context 7-36

Lab: Implementing Stored Procedures and Functions 7-44

Page 2: 9767407- Implementing Stored Procedures and Functions

Information in this document, including URL and other Internet Web site references, is subject to change without notice. Unless otherwise noted, the example companies, organizations, products, domain names, e-mail addresses, logos, people, places, and events depicted herein are fictitious, and no association with any real company, organization, product, domain name, e-mail address, logo, person, place or event is intended or should be inferred. Complying with all applicable copyright laws is the responsibility of the user. Without limiting the rights under copyright, no part of this document may be reproduced, stored in or introduced into a retrieval system, or transmitted in any form or by any means (electronic, mechanical, photocopying, recording, or otherwise), or for any purpose, without the express written permission of Microsoft Corporation.

The names of manufacturers, products, or URLs are provided for informational purposes only and Microsoft makes no representations and warranties, either expressed, implied, or statutory, regarding these manufacturers or the use of the products with any Microsoft technologies. The inclusion of a manufacturer or product does not imply endorsement of Microsoft of the manufacturer or product. Links are provided to third party sites. Such sites are not under the control of Microsoft and Microsoft is not responsible for the contents of any linked site or any link contained in a linked site, or any changes or updates to such sites. Microsoft is not responsible for webcasting or any other form of transmission received from any linked site. Microsoft is providing these links to you only as a convenience, and the inclusion of any link does not imply endorsement of Microsoft of the site or the products contained therein.

Microsoft may have patents, patent applications, trademarks, copyrights, or other intellectual property rights covering subject matter in this document. Except as expressly provided in any written license agreement from Microsoft, the furnishing of this document does not give you any license to these patents, trademarks, copyrights, or other intellectual property.

©2006 Microsoft Corporation. All rights reserved.

Microsoft, JScript, MSDN, Outlook, PowerPoint, Visual Basic, Visual C#, Visual C++, Visual FoxPro, Windows, and Windows Server are either registered tradmarks or trademarks of Microsoft Corporation in the United States and/or other countries.

The names of actual companies and products mentioned herein may be the trademarks of their respective owners.

Page 3: 9767407- Implementing Stored Procedures and Functions

Module 7: Implementing Stored Procedures and Functions 7–1

**************************************** Illegal for non-trainer use ***************************************

Module objectives After completing this module, students will be able to:

■ Implement stored procedures.

■ Create parameterized stored procedures.

■ Implement functions.

■ Handle errors.

■ Control execution context.

Introduction As a database developer, you might be expected to design and implement logic within the database to enforce business rules or data consistency by using stored procedures or user-defined functions. Alternatively, you might be responsible for modifying and maintaining existing modules written by other developers.

In this module, you will learn how to create stored procedures and user-defined functions. You will also learn how to implement structured error handling and deal with execution context.

Page 4: 9767407- Implementing Stored Procedures and Functions

7–2 Module 7: Implementing Stored Procedures and Functions

Lesson 1: Implementing Stored Procedures

**************************************** Illegal for non-trainer use ***************************************

Lesson objectives After completing this lesson, students will be able to:

■ Define stored procedures, and describe the purpose of a stored procedure.

■ Describe the syntax for creating a stored procedure.

■ Describe best practices for creating stored procedures.

■ Describe the syntax for altering or dropping a stored procedure.

Introduction A stored procedure is a group of Transact-SQL statements compiled into a single execution plan. Stored procedures can assist you in achieving a consistent implementation of logic across applications.

This lesson describes what stored procedures are and what benefits they can bring to your database applications. You will also learn how to alter and remove existing stored procedures.

Page 5: 9767407- Implementing Stored Procedures and Functions

Module 7: Implementing Stored Procedures and Functions 7–3

What Is a Stored Procedure?

**************************************** Illegal for non-trainer use ***************************************

What is a stored procedure?

A stored procedure is a named collection of Transact-SQL statements that is stored on the server within the database itself. Stored procedures are a method of encapsulating repetitive tasks; they support user-declared variables, conditional execution, and other powerful programming features.

Stored procedures in Microsoft® SQL Server™ are similar to procedures in other programming languages, in that they can:

■ Contain statements that perform operations in the database, including the ability to call other stored procedures.

■ Accept input parameters.

■ Return a status value to a calling stored procedure or batch to indicate success or failure.

■ Return multiple values to the calling stored procedure or client application in the form of output parameters.

Advantages of stored procedures

Stored procedures offer numerous advantages over executing ad hoc Transact-SQL queries. They can:

Encapsulate business functionality and create reusable application logic. Business rules or policies encapsulated in stored procedures can be changed in a single location. All clients can use the same stored procedures to ensure consistent data access and modification.

Shield users from exposure to the details of the tables in the database. If a set of stored procedures supports all the business functions that users need to perform, users never need to access the tables directly.

Provide security mechanisms. Users can be granted permission to execute a stored procedure even if they do not have permission to access the tables or views to which the stored procedure refers.

Page 6: 9767407- Implementing Stored Procedures and Functions

7–4 Module 7: Implementing Stored Procedures and Functions

Improve performance. Stored procedures implement many tasks as a series of Transact-SQL statements. Conditional logic can be applied to the results of the first Transact-SQL statements to determine which subsequent Transact-SQL statements are executed. All these Transact-SQL statements and conditional logic become part of a single execution plan on the server.

Reduce network traffic. Rather than send hundreds of Transact-SQL statements over the network, users can perform a complex operation by sending a single statement, which reduces the number of requests that pass between client and server.

Reduce vulnerability to SQL injection attacks . Using explicitly defined parameters in SQL code eliminates the possibility that a hacker could submit embedded SQL statements in the parameter values.

Page 7: 9767407- Implementing Stored Procedures and Functions

Module 7: Implementing Stored Procedures and Functions 7–5

Syntax for Creating Stored Procedures

**************************************** Illegal for non-trainer use ***************************************

Introduction You create stored procedures by using the CREATE PROCEDURE statement. Stored procedures can be created only in the current database—except for temporary stored procedures, which are always created in the tempdb database. Creating a stored procedure is similar to creating a view. First write and test the Transact-SQL statements that you want to include in the stored procedure. Then, if you receive the results that you expect, create the stored procedure.

Partial syntax for creating a stored procedure

The CREATE PROCEDURE statement contains many possible options, as shown in the following partial syntax.

CREATE { PROC | PROCEDURE } [schema_name.] procedure_name

[ { @parameter [ type_schema_name. ] data_type }

[ VARYING ] [ = default ] [ [ OUT [ PUT ] ]

[ ,...n ]

[ WITH <procedure_option> [ ,...n ]

AS sql_statement [;][ ...n ]

<procedure_option> ::=

[ ENCRYPTION ]

[ RECOMPILE ]

[ EXECUTE_AS_Clause ]

For More Information For more information about the complete CREATE PROCEDURE syntax, see “CREATE PROCEDURE (Transact-SQL)” in SQL Server Books Online.

Page 8: 9767407- Implementing Stored Procedures and Functions

7–6 Module 7: Implementing Stored Procedures and Functions

Example of creating a simple stored procedure

The following example shows how you can create a simple stored procedure that returns a rowset of all products that take more than one day to manufacture.

CREATE PROC Production.LongLeadProducts

AS

SELECT Name, ProductNumber

FROM Production.Product

WHERE DaysToManufacture >= 1

GO

The previous example creates a procedure named LongLeadProducts within the Production schema. A GO command is included to emphasize the fact that CREATE PROCEDURE statements must be declared within a single batch.

Example of calling a stored procedure

The following example shows how to call the LongLeadProducts stored procedure.

EXEC Production.LongLeadProducts

Page 9: 9767407- Implementing Stored Procedures and Functions

Module 7: Implementing Stored Procedures and Functions 7–7

Guidelines for Creating Stored Procedures

**************************************** Illegal for non-trainer use ***************************************

Stored procedure guidelines

Consider the following guidelines when you create stored procedures:

■ Qualify object names referenced by a stored procedure with the appropriate schema name. This ensures that tables, views, or other objects from different schemas are accessible within the stored procedure. If the referenced object name is not qualified, the stored procedure’s schema is searched by default.

■ Design each stored procedure to accomplish a single task.

■ Create, test, and troubleshoot your stored procedure on the server, and then test it from the client.

■ Avoid using the sp_ prefix when you name local stored procedures to easily distinguish system stored procedures. Another reason to avoid the sp_ prefix for stored procedures in a local database is to avoid unnecessary searches of the master database. When a stored procedure with a name beginning with sp_ is called, SQL Server searches the master database before it searches the local database.

■ Use the same connection settings for all stored procedures. SQL Server saves the settings of both SET QUOTED_IDENTIFIER and SET ANSI_NULLS options when a stored procedure is created or altered. These original settings are used when the stored procedure is executed. Therefore, any client session settings for these SET options are ignored during stored procedure execution.

■ Minimize the use of temporary stored procedures to avoid contention on the system tables in tempdb, a situation that can adversely affect performance.

Page 10: 9767407- Implementing Stored Procedures and Functions

7–8 Module 7: Implementing Stored Procedures and Functions

Syntax for Altering and Dropping Stored Procedures

**************************************** Illegal for non-trainer use ***************************************

Altering stored procedures

Stored procedures are often modified in response to requests from users or to changes in the underlying table definitions. To modify an existing stored procedure and retain permission assignments, use the ALTER PROCEDURE statement. SQL Server replaces the previous definition of the stored procedure when it is altered by using ALTER PROCEDURE.

Consider the following facts when you use the ALTER PROCEDURE statement:

■ If you want to modify a stored procedure that was created by using an option, such as the WITH ENCRYPTION option, you must include the option in the ALTER PROCEDURE statement to retain the functionality that the option provides.

■ ALTER PROCEDURE changes only a single procedure. If your procedure calls other stored procedures, the nested stored procedures are not affected.

Example of altering a stored procedure

The following example modifies the LongLeadProducts stored procedure to select an extra column and to sort the result set by using an ORDER BY clause.

ALTER PROC Production.LongLeadProducts

AS

SELECT Name, ProductNumber, DaysToManufacture

FROM Production.Product

WHERE DaysToManufacture >= 1

ORDER BY DaysToManufacture DESC, Name

GO

Page 11: 9767407- Implementing Stored Procedures and Functions

Module 7: Implementing Stored Procedures and Functions 7–9

Removing stored procedures

Use the DROP PROCEDURE statement to remove user-defined stored procedures from the current database.

Before you drop a stored procedure, execute the sp_depends stored procedure to determine whether objects depend on the stored procedure, as shown in the following example.

EXEC sp_depends @objname = N'Production.LongLeadProducts'

The following example drops the LongLeadProducts stored procedure.

DROP PROC Production.LongLeadProducts

Page 12: 9767407- Implementing Stored Procedures and Functions

7–10 Module 7: Implementing Stored Procedures and Functions

Lesson 2: Creating Parameterized Stored Procedures

**************************************** Illegal for non-trainer use ***************************************

Lesson objectives After completing this lesson, students will be able to:

■ Describe the syntax for using input parameters.

■ Describe the syntax for using output parameters and return values.

Introduction Stored procedures are more flexible when you include parameters as part of the procedure definition because you can create more generic application logic.

In this lesson, you will learn how to include input and output parameters and how to use return values within stored procedures.

Page 13: 9767407- Implementing Stored Procedures and Functions

Module 7: Implementing Stored Procedures and Functions 7–11

Input Parameters

**************************************** Illegal for non-trainer use ***************************************

Introduction A stored procedure communicates with the program that calls the procedure through a list of up to 2,100 parameters. Input parameters allow information to be passed into a stored procedure; these values can then be used as local variables within the procedure.

Guidelines for using input parameters

To define a stored procedure that accepts input parameters, you declare one or more variables as parameters in the CREATE PROCEDURE statement. Consider the following guidelines when using input parameters:

■ Provide default values for a parameter where appropriate. If a default is defined, a user can execute the stored procedure without specifying a value for that parameter.

■ Validate all incoming parameter values at the beginning of a stored procedure to trap missing and invalid values early. This might include checking whether the parameter is NULL.

Example of using input parameters

The following example adds an @MinimumLength parameter to the LongLeadProducts stored procedure. This allows the WHERE clause to be more flexible than previously shown by allowing the calling application to define what length of lead time is considered appropriate.

ALTER PROC Production.LongLeadProducts

@MinimumLength int = 1 -- default value

AS

IF (@MinimumLength < 0) -- validate

BEGIN

RAISERROR('Invalid lead time.', 14, 1)

RETURN

END

SELECT Name, ProductNumber, DaysToManufacture

FROM Production.Product

WHERE DaysToManufacture >= @MinimumLength

ORDER BY DaysToManufacture DESC, Name

Page 14: 9767407- Implementing Stored Procedures and Functions

7–12 Module 7: Implementing Stored Procedures and Functions

The stored procedure defines a default parameter value of 1 so that calling applications can execute the procedure without specifying an argument. If a value is passed to @MinimumLength, it is validated to ensure that the value is appropriate for the purpose of the SELECT statement. If the value is less than zero, an error is raised, and the stored procedure returns immediately without executing the SELECT statement.

Calling parameterized stored procedures

You can set the value of a parameter by passing the value to the stored procedure by either parameter name or position. You should not mix the different formats when you supply values.

Specifying a parameter in an EXECUTE statement in the format @parameter = value is referred to as passing by parameter name. When you pass values by parameter name, the parameter values can be specified in any order, and you can omit parameters that allow null values or that have a default.

The following example calls the LongLeadProducts stored procedure and specifies the parameter name.

EXEC Production.LongLeadProducts @MinimumLength=4

Passing only values (without reference to the parameter names to which they are being passed) is referred to as passing values by position. When you specify only a value, the parameter values must be listed in the order in which they are defined in the CREATE PROCEDURE statement. When you pass values by position, you can omit parameters where defaults exist, but you cannot interrupt the sequence. For example, if a stored procedure has five parameters, you can omit both the fourth and fifth parameters, but you cannot omit the fourth parameter and specify the fifth.

The following example calls the LongLeadProducts stored procedure and specifies the parameter by using the position only.

EXEC Production.LongLeadProducts 4

Using the default values of a parameter

The default value of a parameter, if defined for the parameter in the stored procedure, is used when:

■ No value for the parameter is specified when the stored procedure is executed.

■ The DEFAULT keyword is specified as the value for the parameter.

Page 15: 9767407- Implementing Stored Procedures and Functions

Module 7: Implementing Stored Procedures and Functions 7–13

Output Parameters and Return Values

**************************************** Illegal for non-trainer use ***************************************

Introduction Stored procedures can return information to the calling stored procedure or client by using both output parameters and a return value.

Output parameter characteristics

Output parameters allow any changes to the parameter that result from the execution of the stored procedure to be retained, even after the stored procedure completes execution.

To use an output parameter within Transact-SQL, you must specify the OUTPUT keyword in both the CREATE PROCEDURE and the EXECUTE statements. If the OUTPUT keyword is omitted when the stored procedure is executed, the stored procedure still executes but does not return the modified value. In most client programming languages, such as Microsoft Visual C#®, parameter direction defaults to input, so you must indicate the parameter’s direction in the client.

Example of using output parameters

The following example creates a stored procedure that inserts a new department into the HumanResources.Department table of the AdventureWorks database.

CREATE PROC HumanResources.AddDepartment

@Name nvarchar(50), @GroupName nvarchar(50),

@DeptID smallint OUTPUT

AS

INSERT INTO HumanResources.Department (Name, GroupName)

VALUES (@Name, @GroupName)

SET @DeptID = SCOPE_IDENTITY()

The @DeptID output parameter stores the identity of the new record by calling the SCOPE_IDENTITY function so that a calling application can immediately access the automatically generated ID number.

Page 16: 9767407- Implementing Stored Procedures and Functions

7–14 Module 7: Implementing Stored Procedures and Functions

The following example shows how the calling application can store the results of the stored procedure execution using the local variable @dept.

DECLARE @dept int

EXEC AddDepartment 'Refunds', '', @dept OUTPUT

SELECT @dept

Return values You can also return information from a stored procedure by using the RETURN statement. This method is more limiting than using output parameters because it returns only a single integer value. The RETURN statement is most commonly used to return a status result or an error code from a procedure.

The following example alters the AddDepartment stored procedure to return a success or failure value.

ALTER PROC HumanResources.AddDepartment

@Name nvarchar(50), @GroupName nvarchar(50),

@DeptID smallint OUTPUT

AS

IF ((@Name = '') OR (@GroupName = ''))

RETURN -1

INSERT INTO HumanResources.Department (Name, GroupName)

VALUES (@Name, @GroupName)

SET @DeptID = SCOPE_IDENTITY()

RETURN 0

If an empty string is passed to the procedure for either the @Name or @GroupName parameter, a -1 value is returned to indicate failure. If the INSERT statement succeeds, a 0 value is returned to indicate success.

The following example shows how the calling application can store the return value of the stored procedure execution by using the local variable @result.

DECLARE @dept int, @result int

EXEC @result = AddDepartment 'Refunds', '', @dept OUTPUT

IF (@result = 0)

SELECT @dept

ELSE

SELECT 'Error during insert'

Note SQL Server automatically returns a 0 from stored procedures if you do not specify your own RETURN value.

Page 17: 9767407- Implementing Stored Procedures and Functions

Module 7: Implementing Stored Procedures and Functions 7–15

Practice: Creating a Parameterized Stored Procedure

**************************************** Illegal for non-trainer use ***************************************

Goals The goal of this practice is to create a stored procedure that accepts input parameters and returns output parameters along with a success or failure flag.

Preparation Ensure that virtual machine 2779A-MIA-SQL-07 is running and that you are logged on as Student.

If a virtual machine has not been started, perform the following steps:

1. Close any other running virtual machines.

2. Start the virtual machine.

3. In the Log On to Windows dialog box, complete the logon procedure by using the user name Student and the password Pa$$w0rd.

To create a simple stored procedure

� Perform the following steps to create a simple stored procedure:

1. Click Start, point to All Programs, point to Microsoft SQL Server 2005, and then click SQL Server Management Studio.

2. In the Connect to Server dialog box, specify the values in the following table, and then click Connect.

3. On the File menu, point to Open, and then click File.

4. Open the StoredProcedures.sql query file in the D:\Practices folder. Connect to MIAMI by using Windows authentication when prompted.

5. Examine the code under the comment Get reviews for all products, and then select the code and click Execute.

Property Value

Server type Database Engine

Server name MIAMI

Authentication Windows Authentication

Page 18: 9767407- Implementing Stored Procedures and Functions

7–16 Module 7: Implementing Stored Procedures and Functions

6. Review the query output and confirm that the command completed successfully.

7. Select the query under the comment Test stored procedure, and then on the toolbar, click Execute.

8. Review the query results.

To create a stored procedure that accepts an input parameter

� Perform the following steps to create a stored procedure that accepts an input parameter:

1. Select the ALTER PROCEDURE statement under the comment Alter procedure to get specific product review, and then on the toolbar, click Execute.

2. Review the query output and confirm that the command completed successfully.

3. Select the query under the comment Test procedure with parameter, and then on the toolbar, click Execute.

4. Review the query results. Notice that the first EXECUTE statement produced the correct results but that the second EXECUTE statement failed because the parameter was not passed to the procedure and the parameter does not have a default value within the procedure.

5. Select the ALTER PROCEDURE statement under the comment Alter procedure to get specific product review or all reviews, and then on the toolbar, click Execute.

6. Review the query output and confirm that the command completed successfully.

7. Select the query under the comment Test procedure with parameter and default, and then on the toolbar, click Execute.

8. Review the query results. Notice that the first EXECUTE statement produces results for the specified product and that the second EXECUTE statement produces results for all products.

To create a stored procedure that accepts an output parameter and returns values

� Perform the following steps to create a stored procedure that accepts an output parameter and returns a success or failure value:

1. Select the ALTER PROCEDURE statement under the comment Alter procedure to output number of reviews and check product exists, and then on the toolbar, click Execute.

2. Review the query output and confirm that the command completed successfully.

3. Select the queries between the comment Test output and return values and the GO statement, and on the toolbar, click Execute.

4. Review the query results. Notice that the results are displayed correctly, followed by the number of reviews from the output parameter.

5. Modify the EXECUTE statement by removing the OUTPUT keyword.

6. Reselect the queries between the comment Test output and return values and the GO statement, and then on the toolbar, click Execute.

7. Review the query results. Notice that the results are displayed correctly but that the number of reviews returns NULL because the OUTPUT keyword was removed.

8. Modify the EXECUTE statement by putting the OUTPUT keyword back and changing the input parameter from 937 to DEFAULT.

9. Reselect the queries between the comment Test output and return values and the GO statement, and then on the toolbar, click Execute.

Page 19: 9767407- Implementing Stored Procedures and Functions

Module 7: Implementing Stored Procedures and Functions 7–17

10. Review the query results. Notice that all reviews are now returned and that the number of reviews has increased.

11. Modify the EXECUTE statement by changing the input parameter from DEFAULT to 100.

12. Reselect the queries between the comment Test output and return values and the GO statement, and then on the toolbar, click Execute.

13. Review the query results. Notice that no reviews are returned and that the message ProductID does not exist is displayed because an invalid product ID was used.

To drop a stored procedure

� Perform the following steps to drop a stored procedure:

1. Select the DROP PROCEDURE statement under the comment Drop the procedure, and then on the toolbar, click Execute.

2. Review the query output and confirm that the command completed successfully.

3. Close SQL Server Management Studio without saving any changes to the file.

Page 20: 9767407- Implementing Stored Procedures and Functions

7–18 Module 7: Implementing Stored Procedures and Functions

Lesson 3: Creating Functions

**************************************** Illegal for non-trainer use ***************************************

Lesson objectives After completing this lesson, students will be able to:

■ Describe the different types of functions.

■ Describe how a scalar function works.

■ Describe how an inline table-valued function works.

■ Describe how a multi-statement table-valued function works.

Introduction Functions are routines that are used to encapsulate frequently performed logic. Rather than having to repeat all the function logic, any code that must perform the logic can call the function.

This lesson provides an overview of functions and explains why and how you use them, in addition to the syntax for creating them.

Page 21: 9767407- Implementing Stored Procedures and Functions

Module 7: Implementing Stored Procedures and Functions 7–19

Types of Functions

**************************************** Illegal for non-trainer use ***************************************

What are functions? Functions are routines made up of one or more Transact-SQL statements that can be used to encapsulate code for reuse. A function takes zero or more input parameters and returns either a scalar value or a table. Input parameters can be any data type except timestamp, cursor, or table, but functions do not support output parameters.

Scalar functions Scalar functions return a single data value of the type defined in a RETURNS clause. These types of functions are syntactically very similar to built-in system functions such as COUNT or MAX.

Inline table-valued functions

An inline table-valued function returns a table that is the result of a single SELECT statement. It is similar to a view but offers more flexibility than views do because you can supply parameters to the function.

Multi-statement table-valued functions

A multi-statement table-valued function returns a table built by one or more Transact-SQL statements and is similar to a stored procedure. Unlike a stored procedure, a multi-statement table-valued function can be referenced in the FROM clause of a SELECT statement as if it were a view or table.

Page 22: 9767407- Implementing Stored Procedures and Functions

7–20 Module 7: Implementing Stored Procedures and Functions

What Is a Scalar Function?

**************************************** Illegal for non-trainer use ***************************************

Creating scalar functions A scalar function returns a single data value of the type defined in a RETURNS clause. The body of the function, defined in a BEGIN…END block, contains the series of Transact-SQL statements that return the value.

The following example creates a scalar function that totals all of the sales for a particular product in the AdventureWorks database and returns the total as an int.

CREATE FUNCTION Sales.SumSold(@ProductID int) RETURNS int

AS

BEGIN

DECLARE @ret int

SELECT @ret = SUM(OrderQty)

FROM Sales.SalesOrderDetail WHERE ProductID = @ProductID

IF (@ret IS NULL)

SET @ret = 0

RETURN @ret

END

Note When altering or dropping a function, you use a similar syntax to altering and dropping other database objects. Use ALTER FUNCTION to modify your functions after creation, and use DROP FUNCTION to remove the functions from the database.

Page 23: 9767407- Implementing Stored Procedures and Functions

Module 7: Implementing Stored Procedures and Functions 7–21

Invoking scalar functions A user-defined function that returns a scalar value can be invoked anywhere a scalar expression of the same data type is allowed in Transact-SQL statements. The following table contains examples of where you can use scalar functions.

The following example performs a SELECT statement that retrieves the ProductID, the Name, and the result of the SumSold scalar function for each product record in AdventureWorks.

SELECT ProductID, Name, Sales.SumSold(ProductID) AS SumSold

FROM Production.Product

Area Example

Queries ■ As an expression in the select_list of a SELECT statement.

■ As an expression or string_expression in a WHERE or HAVING clause.

■ As a group_by_expression in a GROUP BY clause.

■ As an order_by_expression in an ORDER BY clause.

■ As an expression in the SET clause in an UPDATE statement.

■ As an expression in the VALUES clause of an INSERT statement.

Table definition ■ CHECK constraints. Functions can reference only columns in the same table.

■ DEFAULT definitions. Functions can contain only constants.

■ Computed columns. Functions can reference only columns in the same table.

Transact-SQL statements

■ In assignment operators.

■ In Boolean expressions of control-of-flow statements.

■ In CASE expressions.

■ In PRINT statements (only for functions that return a character string).

Functions and stored procedures

■ As function arguments.

■ As a stored procedure’s RETURN statement (only for scalar functions that return an integer).

■ As a user-defined function’s RETURN statement, provided the value returned by the invoked user-defined function can be implicitly converted to the return data type of the invoking function.

Page 24: 9767407- Implementing Stored Procedures and Functions

7–22 Module 7: Implementing Stored Procedures and Functions

What Is an Inline Table-Valued Function?

**************************************** Illegal for non-trainer use ***************************************

When to use inline table-valued functions

You can use inline functions to achieve the functionality of parameterized views. One of the limitations of a view is that you are not allowed to include a user-provided parameter within the view when you create it. You can usually resolve this by providing a WHERE clause when calling the view. However, this might require building a string for dynamic execution, which can increase the complexity of the application. You can achieve the functionality of a parameterized view by using an inline table-valued function.

Consider the following characteristics of inline table-valued user-defined functions:

■ The RETURNS statement specifies table as the data type returned.

■ The result set of the SELECT statement defines the format of a return variable.

■ The RETURN clause contains a single SELECT statement in parentheses. The SELECT statement used in an inline function is subject to the same restrictions as SELECT statements used in views.

■ The body of the function does not need to be enclosed in a BEGIN…END block.

Example of an inline table-valued function

The following example creates an inline table-valued function that returns the names of employees for a particular manager in the AdventureWorks database.

CREATE FUNCTION HumanResources.EmployeesForManager

(@ManagerId int)

RETURNS TABLE

AS

RETURN (

SELECT FirstName, LastName

FROM HumanResources.Employee Employee INNER JOIN

Person.Contact Contact

ON Employee.ContactID = Contact.ContactID

WHERE ManagerID = @ManagerId )

Page 25: 9767407- Implementing Stored Procedures and Functions

Module 7: Implementing Stored Procedures and Functions 7–23

Invoking inline table-valued functions

Use an inline table-valued function anywhere that you would normally use a view, such as in the FROM clause of a SELECT statement. The following examples retrieve all employee names for two managers.

SELECT * FROM HumanResources.EmployeesForManager(3)

-- OR

SELECT * FROM HumanResources.EmployeesForManager(6)

Page 26: 9767407- Implementing Stored Procedures and Functions

7–24 Module 7: Implementing Stored Procedures and Functions

What Is a Multi-Statement Table-Valued Function?

**************************************** Illegal for non-trainer use ***************************************

When to use multi-statement table-valued functions

A multi-statement table-valued function is a combination of a view and a stored procedure. You can use user-defined functions that return a table to replace stored procedures or views.

A table-valued function (like a stored procedure) can use complex logic and multiple Transact-SQL statements to build a table. In the same way that you use a view, you can use a table-valued function in the FROM clause of a Transact-SQL statement.

Consider the following characteristics of multi-statement table-valued functions:

■ The RETURNS statement specifies table as the returned data type and defines a name for the table and the format.

■ A BEGIN…END block delimits the body of the function.

Example of a multi-statement table-valued function

The following example creates a table variable named @tbl_Employees with two columns. The second column changes depending on the requested @format parameter value.

CREATE FUNCTION HumanResources.EmployeeNames

(@format nvarchar(9))

RETURNS @tbl_Employees TABLE

(EmployeeID int PRIMARY KEY, [Employee Name] nvarchar(100))

AS

BEGIN

IF (@format = 'SHORTNAME')

INSERT @tbl_Employees

SELECT EmployeeID, LastName

FROM HumanResources.vEmployee

ELSE IF (@format = 'LONGNAME')

INSERT @tbl_Employees

SELECT EmployeeID, (FirstName + ' ' + LastName)

FROM HumanResources.vEmployee

RETURN

END

Page 27: 9767407- Implementing Stored Procedures and Functions

Module 7: Implementing Stored Procedures and Functions 7–25

Invoking multi-statement table-valued functions

You can call the function in the FROM clause instead of by using a table or a view. The following examples retrieve the employee names in both long and short formats.

SELECT * FROM HumanResources.EmployeeNames('LONGNAME')

-- OR

SELECT * FROM HumanResources.EmployeeNames('SHORTNAME')

Page 28: 9767407- Implementing Stored Procedures and Functions

7–26 Module 7: Implementing Stored Procedures and Functions

Practice: Creating Functions

**************************************** Illegal for non-trainer use ***************************************

Goals The goal of this practice is to create a scalar function, an inline table-valued function, and a multi-statement table-valued function.

Preparation Ensure that virtual machine 2779A-MIA-SQL-07 is running and that you are logged on as Student.

If a virtual machine has not been started, perform the following steps:

1. Close any other running virtual machines.

2. Start the virtual machine.

3. In the Log On to Windows dialog box, complete the logon procedure by using the user name Student and the password Pa$$w0rd.

To create a scalar function

� Perform the following steps to create a scalar function:

1. Click Start, point to All Programs, point to Microsoft SQL Server 2005, and then click SQL Server Management Studio.

2. In the Connect to Server dialog box, specify the values in the following table, and then click Connect.

3. On the File menu, point to Open, and then click File.

4. Open the UserDefinedFunctions.sql query file in the D:\Practices folder. Connect to MIAMI by using Windows authentication when prompted.

5. Select the code under the comment Create scalar function, and then on the toolbar, click Execute.

Property Value

Server type Database Engine

Server name MIAMI

Authentication Windows Authentication

Page 29: 9767407- Implementing Stored Procedures and Functions

Module 7: Implementing Stored Procedures and Functions 7–27

6. Review the query output and confirm that the command completed successfully.

7. Select the query under the comment Test scalar function in SELECT, and then on the toolbar, click Execute.

8. Review the query results. Notice that most products do not have a review and therefore display an average rating of 0.

9. Select the query under the comment Test scalar function in WHERE, and then on the toolbar, click Execute.

10. Review the query results. Notice that only the products that have reviews are returned.

To create an inline table-valued function

� Perform the following steps to create an inline table-valued function:

1. Select the CREATE FUNCTION statement under the comment Create inline function, and then on the toolbar, click Execute.

2. Review the query output and confirm that the command completed successfully.

3. Select the query under the comment Test inline function, and then on the toolbar, click Execute.

4. Review the query results. Notice that only the reviews for the one product are displayed.

To create a multi-statement table-valued function

� Perform the following steps to create a multi-statement table-valued function:

1. Select the CREATE FUNCTION statement under the comment Create multi-statement function, and then on the toolbar, click Execute.

2. Review the query output and confirm that the command completed successfully.

3. Select the queries between the comment Test multi-statement function and the GO statement, and then on the toolbar, click Execute.

4. Review the query results. Notice that the first result set contains ratings of three or more and the second result set contains ratings of less than three.

To drop user-defined functions

� Perform the following steps to drop user-defined functions:

1. Select the DROP FUNCTION statements under the comment Drop user-defined functions, and then on the toolbar, click Execute.

2. Review the query output and confirm that the command completed successfully.

3. Close SQL Server Management Studio without saving any changes to the file.

Page 30: 9767407- Implementing Stored Procedures and Functions

7–28 Module 7: Implementing Stored Procedures and Functions

Lesson 4: Handling Errors

**************************************** Illegal for non-trainer use ***************************************

Lesson objectives After completing this lesson, students will be able to:

■ Describe the syntax for structured exception handling.

■ Describe best practices for handling errors.

Introduction This lesson introduces the Microsoft SQL Server 2005 structured exception-handling technique. Exception handling is an important requirement for many Transact-SQL statements, particularly those that involve transactions. Structured exception handling reduces the amount of work required to handle errors and makes your code more reliable.

Page 31: 9767407- Implementing Stored Procedures and Functions

Module 7: Implementing Stored Procedures and Functions 7–29

Syntax for Structured Exception Handling

**************************************** Illegal for non-trainer use ***************************************

Introduction Structured exception handling is a common way to handle exceptions in many popular programming languages, such as Microsoft Visual Basic® and Visual C#. SQL Server 2005 allows you to use structured exception handling in any transactional situation, such as a stored procedure. This makes your code more readable and more maintainable.

Syntax for structured error handling

Use TRY…CATCH blocks to implement structured exception handling. The TRY block contains the transactional code that could potentially fail. The CATCH block contains the code that executes if an error occurs in the TRY block.

TRY…CATCH has the following syntax.

BEGIN TRY

{ sql_statement | statement_block }

END TRY

BEGIN CATCH

{ sql_statement | statement_block }

END CATCH

The sql_statement or statement_block part of the syntax is any Transact-SQL statement or group of statements.

Example of TRY…CATCH In this example, a stored procedure named AddData attempts to insert two values into a table named TestData. The first column of the TestData table is an integer primary key, and the second column is an integer data type. A TRY…CATCH block within the AddData stored procedure protects the TestData INSERT statement and returns the error number and error message as part of the CATCH block logic by using the ERROR_NUMBER and ERROR_MESSAGE functions.

CREATE TABLE dbo.TableWithKey (ColA int PRIMARY KEY, ColB int)

GO

CREATE PROCEDURE dbo.AddData @a int, @b int

AS

Page 32: 9767407- Implementing Stored Procedures and Functions

7–30 Module 7: Implementing Stored Procedures and Functions

BEGIN TRY

INSERT INTO TableWithKey VALUES (@a, @b)

END TRY

BEGIN CATCH

SELECT ERROR_NUMBER() ErrorNumber, ERROR_MESSAGE() [Message]

END CATCH

GO

EXEC dbo.AddData 1, 1

EXEC dbo.AddData 2, 2

EXEC dbo.AddData 1, 3 --violates the primary key

Page 33: 9767407- Implementing Stored Procedures and Functions

Module 7: Implementing Stored Procedures and Functions 7–31

Guidelines for Handling Errors

**************************************** Illegal for non-trainer use ***************************************

Creating the CATCH block Create the CATCH block immediately following the END TRY statement by using the BEGIN CATCH and END CATCH statements. You cannot include any other statement between the END TRY and BEGIN CATCH statements.

The following example will not compile.

BEGIN TRY

-- INSERT INTO ...

END TRY

SELECT * FROM TableWithKey -- NOT ALLOWED

BEGIN CATCH

-- SELECT ERROR_NUMBER()

END CATCH

Rolling back failed transactions

Using transactions allows you to group together multiple statements so that either they all complete successfully or none of them complete successfully. Consider the following example, which does not use transactions.

CREATE TABLE dbo.TableNoKey (ColA int, ColB int)

CREATE TABLE dbo.TableWithKey (ColA int PRIMARY KEY, ColB int)

GO

CREATE PROCEDURE dbo.AddData @a int, @b int

AS

BEGIN TRY

INSERT dbo.TableNoKey VALUES (@a, @b)

INSERT dbo.TableWithKey VALUES (@a, @b)

END TRY

BEGIN CATCH

SELECT ERROR_NUMBER() ErrorNumber, ERROR_MESSAGE() [Message]

END CATCH

GO

EXEC dbo.AddData 1, 1

EXEC dbo.AddData 2, 2

EXEC dbo.AddData 1, 3 --violates the primary key

Page 34: 9767407- Implementing Stored Procedures and Functions

7–32 Module 7: Implementing Stored Procedures and Functions

This example performs two sequential inserts into two different tables. The first insert will always succeed because there is no primary key constraint on the table. The second insert will fail whenever a duplicate ColA value is inserted. Because transactions are not used in this example, the first insert succeeds even when the second insert fails, potentially leading to unexpected results.

The following example uses transactions to ensure that neither insert succeeds if any one of the inserts fails. It does this by using BEGIN TRAN and COMMIT TRAN statements within the TRY block and a ROLLBACK TRAN statement within the CATCH block.

ALTER PROCEDURE dbo.AddData @a int, @b int

AS

BEGIN TRY

BEGIN TRAN

INSERT dbo.TableNoKey VALUES (@a, @b)

INSERT dbo.TableWithKey VALUES (@a, @b)

COMMIT TRAN

END TRY

BEGIN CATCH

ROLLBACK TRAN

SELECT ERROR_NUMBER() ErrorNumber, ERROR_MESSAGE() [Message]

END CATCH

GO

Using XACT_ABORT and XACT_STATE

The XACT_ABORT option specifies whether SQL Server automatically rolls back the current transaction when a Transact-SQL statement raises a run-time error. However, if the error occurs within a TRY block, the transaction is not automatically rolled back; instead, it becomes uncommittable.

Code within a CATCH block should test for the state of a transaction by using the XACT_STATE function. XACT_STATE returns a –1 if an uncommittable transaction is present in the current session. The CATCH block must not attempt to commit the transaction and should roll back the transaction manually. A returned value of 1 from XACT_STATE means that there is a transaction that can be safely committed. A returned value of 0 means that there is no current transaction.

The following example sets XACT_ABORT ON and tests the transaction state within the CATCH block.

SET XACT_ABORT ON

BEGIN TRY

BEGIN TRAN

...

COMMIT TRAN

END TRY

BEGIN CATCH

IF (XACT_STATE()) = -1 -- uncommittable

ROLLBACK TRAN

ELSE IF (XACT_STATE()) = 1 -- committable

COMMIT TRAN

END CATCH

For More Information For more information about using XACT_ABORT and XACT_STATE, see “Using TRY...CATCH in Transact-SQL” in SQL Server Books Online.

Page 35: 9767407- Implementing Stored Procedures and Functions

Module 7: Implementing Stored Procedures and Functions 7–33

Capturing error information if required

SQL Server provides several error-related functions that you can call within your CATCH block for logging error information. For example, you could call these methods and store the results in an error log table.

The following table lists the error functions.

For More Information For more information about error severity levels, see “Database Engine Error Severities” in SQL Server Books Online.

Function Description

ERROR_LINE Returns the line number at which the error occurred that caused the CATCH block code to execute.

ERROR_MESSAGE Returns diagnostic information about the cause of the error. Many error messages have substitution variables in which information, such as the name of the object generating the error, is placed.

ERROR_NUMBER Returns the unique number for the error that occurred.

ERROR_PROCEDURE Returns the name of the stored procedure or trigger in which the error occurred.

ERROR_SEVERITY Returns a value indicating how serious the error is. Errors with a low severity, such as 1 or 2, are information messages or low-level warnings. Errors with a high severity indicate problems that should be addressed as soon as possible.

ERROR_STATE Returns the state value. Some error messages can be raised at multiple points in the code for the database engine. Each specific condition that raises an error assigns a unique state code. This information can be useful when you are working with Microsoft Knowledge Base articles to determine whether the recorded issue is the same as the error you have encountered.

Page 36: 9767407- Implementing Stored Procedures and Functions

7–34 Module 7: Implementing Stored Procedures and Functions

Practice: Handling Errors

**************************************** Illegal for non-trainer use ***************************************

Goals The goal of this practice is to add error handling to a stored procedure.

Preparation Ensure that virtual machine 2779A-MIA-SQL-07 is running and that you are logged on as Student.

If a virtual machine has not been started, perform the following steps:

1. Close any other running virtual machines.

2. Start the virtual machine.

3. In the Log On to Windows dialog box, complete the logon procedure by using the user name Student and the password Pa$$w0rd.

To add error handling to a stored procedure

� Perform the following steps to add error handling to a stored procedure:

1. Click Start, point to All Programs, point to Microsoft SQL Server 2005, and then click SQL Server Management Studio.

2. In the Connect to Server dialog box, specify the values in the following table, and then click Connect.

3. On the File menu, point to Open, and then click File.

4. Open the ErrorHandling.sql query file in the D:\Practices folder. Connect to MIAMI by using Windows authentication when prompted.

5. Select the code under the comment Create procedure without error handling, and then on the toolbar, click Execute.

6. Review the query output and confirm that the command completed successfully.

Property Value

Server type Database Engine

Server name MIAMI

Authentication Windows Authentication

Page 37: 9767407- Implementing Stored Procedures and Functions

Module 7: Implementing Stored Procedures and Functions 7–35

7. Select the EXECUTE and SELECT queries under the comment Test stored procedure without error handling, and then on the toolbar, click Execute.

8. Review the query results. Notice that the review was added successfully to the table.

9. Change the @Rating parameter value from 4 to 10.

10. Reselect the EXECUTE and SELECT queries under the comment Test stored procedure without error handling, and then on the toolbar, click Execute.

11. Review the query results. Notice that the insert fails because of a CHECK constraint on the ratings column.

12. Select the ALTER PROCEDURE statement under the comment Implement error handling, and then on the toolbar, click Execute.

13. Review the query output and confirm that the command completed successfully.

14. Select the EXECUTE query under the comment Test stored procedure with error handling, and then on the toolbar, click Execute.

15. Review the query results. Notice that the error number and message are displayed because the CATCH block handles the error successfully.

16. Select the DROP PROCEDURE statement at the end of the file, click Execute.

17. Close SQL Server Management Studio without saving any changes to the file.

Page 38: 9767407- Implementing Stored Procedures and Functions

7–36 Module 7: Implementing Stored Procedures and Functions

Lesson 5: Controlling Execution Context

**************************************** Illegal for non-trainer use ***************************************

Lesson objectives After completing this lesson, students will be able to:

■ Define execution context.

■ Describe how to control execution context by using the EXECUTE AS clause.

■ Describe how to control impersonation context by signing a code module.

■ Control execution context.

Introduction In this lesson, you will learn about execution context and how it affects the way your stored procedures and functions run. You will also learn how to modify the execution context by using the EXECUTE AS clause and about the issues involved in cross-database impersonation.

Page 39: 9767407- Implementing Stored Procedures and Functions

Module 7: Implementing Stored Procedures and Functions 7–37

What Is Execution Context?

**************************************** Illegal for non-trainer use ***************************************

Execution context definition

Execution context establishes the identity against which permissions are checked. The user or login calling a module, such as a stored procedure or function, usually determines execution context.

Example of execution context

Execution context is the identity used by the code when it is executed, and by default, that means the caller, which can create problems if the ownership chain is broken, as described in the following example.

If a user named John owns a table named Sales.Order and he grants SELECT permissions only to the user Pat, the user Ted cannot access this table, as shown in the illustration.

If Pat owns a stored procedure named GetOrders that reads data from the Sales.Order table, Pat can execute this stored procedure without any security problems because Pat has SELECT permissions on the table.

If Pat grants EXECUTE permission on the stored procedure to Ted, this would result in an error when Ted attempts to run the procedure. This is because by default the stored procedure executes as Ted, and he does not have SELECT permission on the Sales.Order table.

To allow Ted to successfully execute the stored procedure, execution context must change to a user that has the appropriate permissions required. You can use the EXECUTE AS clause to switch execution contexts for the stored procedure, as discussed in the next topic.

Note This example also demonstrates a broken ownership chain because Sales.Order and GetOrders are owned by different users. For more information about ownership chains, see “Ownership Chains” in SQL Server Books Online.

Page 40: 9767407- Implementing Stored Procedures and Functions

7–38 Module 7: Implementing Stored Procedures and Functions

The EXECUTE AS Clause

**************************************** Illegal for non-trainer use ***************************************

Introduction You can use the EXECUTE AS clause in a stored procedure or function to set the identity used in its execution context. Understanding how to use the EXECUTE AS clause can help you implement security in scenarios in which you need to access dependent objects but you do not want to rely on unbroken ownership chains.

EXECUTE AS options You can use the EXECUTE AS clause with any CREATE PROCEDURE statement and any CREATE FUNCTION statement except inline table-valued function declarations. The syntax for the EXECUTE AS clause is shown here.

EXECUTE AS { CALLER | SELF | OWNER | user_name }

The options included in the syntax of the EXECUTE AS clause are described in the following table.

Option Description

CALLER Execute by using the identity of the calling user. This is the default setting.

SELF Execute by using the identity of the user who is creating or altering the stored procedure or function. This value is unaffected if another user takes ownership of the module.

OWNER Execute by using the identity of the owner of the function. This value changes if another user takes ownership of the module.

user_name Execute by using the identity of the specified user. If user_name is the same as the user creating or modifying the module, this is equivalent to EXECUTE AS SELF.

Page 41: 9767407- Implementing Stored Procedures and Functions

Module 7: Implementing Stored Procedures and Functions 7–39

Example of using EXECUTE AS

To solve the problem described in the previous topic, specifying the user_name Pat allows Ted to execute the stored procedure successfully, as shown in the following example.

CREATE PROCEDURE GetOrders

WITH EXECUTE AS 'Pat'

AS

SELECT * FROM Sales.Order

Note You can also use EXECUTE AS as a stand-alone Transact-SQL statement to temporarily change the current execution context of any connection until a REVERT statement is issued. For more information, see “REVERT (Transact-SQL)” in SQL Server Books Online.

Page 42: 9767407- Implementing Stored Procedures and Functions

7–40 Module 7: Implementing Stored Procedures and Functions

Options for Extending Impersonation Context

**************************************** Illegal for non-trainer use ***************************************

Limitations of EXECUTE AS

When you use the EXECUTE AS clause to change the execution context so that a code module executes as a user other than the caller, the code is said to “impersonate” the alternative user. By default, the resulting impersonation context is valid only within the scope of the current database. This means that if you create a stored procedure that calls a table in a separate database, the EXECUTE AS clause will pass the impersonation context to the other database, but the context will be invalid.

Establishing a trust relationship to extend impersonation

You can selectively extend the scope of the database impersonation established within a database by establishing a trust model between the two databases. This would be useful with an application that uses two databases and requires access to one database from the other database.

SQL Server 2005 uses authenticators to determine whether an established context is valid within a particular scope. Frequently, the authenticator is either the system administrator or the instance of SQL Server, or in databases, the dbo user. The authenticator is effectively the owner of the scope within which the context for a particular user or login is established.

The validity of the impersonated user context outside the scope of the database depends on whether the authenticator for the context is trusted within the target scope. This trust is established by creating a duplicate authenticator login and granting AUTHENTICATE permission if the target scope is another database or AUTHENTICATE SERVER permission if the target scope is an instance of SQL Server. The calling database must also be marked as TRUSTWORTHY.

The basic steps for establishing a trust relationship for the dbo user are:

1. Create a user in the target database for the same login as the dbo in the calling database. This will be the authenticator in the target database.

2. Grant the mapped user AUTHENTICATE (or AUTHENTICATE SERVER) permission in the target database.

Page 43: 9767407- Implementing Stored Procedures and Functions

Module 7: Implementing Stored Procedures and Functions 7–41

3. Grant the authenticator the permissions required by the stored procedure in the calling database.

4. Alter the calling database and set the TRUSTWORTHY option to ON.

Using certificates and signing to validate callers

An alternative way to establish a trust relationship between databases is to use certificates or asymmetric keys as authenticators. This takes advantage of a technique called signing.

A signature on a module verifies that a person can modify the code within a module only if that person has access to the private key that is used to sign the module. This allows you to set up a trust relationship with the certificate used for the signing rather than with just the database owner. Trust of the signed module is accomplished by granting AUTHENTICATE or AUTHENTICATE SERVER permission to the user in the target scope that is mapped to the certificate or asymmetric key.

The basic steps for using certificates and signing to validate callers are:

1. Create a certificate by using the CREATE CERTIFICATE statement within the calling database.

2. Add a signature to the calling stored procedure by using ADD SIGNATURE.

3. Import the certificate into the target database. This can be achieved by backing up the certificate from the calling database to a file and then using CREATE CERTIFICATE in the target database, referencing the backed-up certificate file.

4. Create a user based on the certificate by using the FROM CERTIFICATE clause of the CREATE USER statement, and grant the user appropriate permissions on the required database objects.

5. Grant AUTHENTICATE or AUTHENTICATE SERVER permission to the user based on the certificate.

For More Information For more information about extending impersonation context, see “Extending Database Impersonation by Using EXECUTE AS” in SQL Server Books Online.

Page 44: 9767407- Implementing Stored Procedures and Functions

7–42 Module 7: Implementing Stored Procedures and Functions

Demonstration: Controlling Execution Context

**************************************** Illegal for non-trainer use ***************************************

Introduction You can create stored procedures or user-defined functions that specify an execution context to avoid permission-related problems when the module calls other database objects. You can use the EXECUTE AS clause of the CREATE PROCEDURE statement to impersonate a different user while the stored procedure executes.

Using execution context within a stored procedure

To create a stored procedure that specifies execution context:

1. Click Start, point to All Programs, point to Microsoft SQL Server 2005, and then click SQL Server Management Studio.

2. In the Connect to Server dialog box, specify the values in the following table, and then click Connect.

3. On the File menu, point to Open, and then click File.

4. Open the ExecutionContext.sql query file in the D:\Democode folder. Connect to MIAMI by using Windows authentication when prompted.

5. Select the code under the comment Preparation tasks, and then on the toolbar, click the Execute button. This creates logins for two Windows users and corresponding users in the AdventureWorks database.

6. Select the code under the comment Execute as CALLER, and then on the toolbar, click the Execute button. This creates the DisplayContext stored procedure.

7. Select the code under the comment Grant user permissions, and then on the toolbar, click the Execute button. This allows both users to access the DisplayContext stored procedure.

Property Value

Server type Database Engine

Server name MIAMI

Authentication Windows Authentication

Page 45: 9767407- Implementing Stored Procedures and Functions

Module 7: Implementing Stored Procedures and Functions 7–43

8. Click Start and Run, and execute the following command:

runas /noprofile /user:MIAMI\Lori cmd

Enter Pa$$w0rd when prompted for Lori’s password.

9. In the new command prompt window, execute the following command:

sqlcmd -E -Q "EXEC dbo.DisplayContext"

You will be connected to SQL Server as Lori, and the DisplayContext stored procedure will be executed. The UserName returned is that of the CALLER, Lori.

10. Leave the command prompt window open, and then return to SQL Server Management Studio.

11. Select the code under the comment Execute as 'Adam', and then on the toolbar, click the Execute button. This alters the DisplayContext stored procedure to execute as Adam.

12. Leave SQL Server Management Studio open, and then return to the command prompt window with the title cmd (running as MIAMI\Lori). Repeat the previous command by pressing the UP ARROW key. The UserName returned is Adam.

13. Leave the command prompt window open, and then return to SQL Server Management Studio.

14. Select the code under the comment Execute as OWNER, and then on the toolbar, click the Execute button. This alters the DisplayContext stored procedure to execute as the owner of the stored procedure.

15. Leave SQL Server Management Studio open, and then return to the command prompt window with the title cmd (running as MIAMI\Lori). Repeat the previous command by pressing the UP ARROW key. The UserName returned is dbo.

16. Leave the command prompt window open, and then return to SQL Server Management Studio.

17. Select the code under the comment Clean up, and then on the toolbar, click the Execute button. This removes the stored procedure and users from the database.

18. Close SQL Server Management Studio, and then close the command prompt windows.

Page 46: 9767407- Implementing Stored Procedures and Functions

7–44 Module 7: Implementing Stored Procedures and Functions

Lab: Implementing Stored Procedures and Functions

**************************************** Illegal for non-trainer use ***************************************

Scenario Adventure Works maintains a list of special offers and discounts for various products throughout the year that applies to both customers and resellers. Currently, this information is only accessible directly from the Sales.SpecialOffer table. A new requirement is to retrieve this information by using stored procedures and user-defined functions, as well as to insert new special offers by using a stored procedure.

The senior database developer has provided you with a SQL Server Scripts project named AWProgrammability.ssmssln in the D:\Labfiles\Starter folder and has specified the following requirements for the modifications you must make:

■ Create a stored procedure named GetDiscounts within the Sales schema that retrieves the following columns from Sales.SpecialOffer: Description, DiscountPct, Type, Category, StartDate, EndDate, MinQty, and MaxQty. The procedure should return all rows sorted by StartDate and EndDate.

■ Create a stored procedure named GetDiscountsForCategory within the Sales schema that accepts an input parameter named @Category, which is an nvarchar data type accepting up to 50 characters. The procedure should retrieve the same columns as for GetDiscounts but should filter the rows based on the @Category parameter.

■ Create a stored procedure named GetDiscountsForCategoryAndDate within the Sales schema that accepts the @Category parameter as for GetDiscountsForCategory but includes an additional @DateToCheck datetime input parameter.

The @DateToCheck parameter must be able to accept a NULL default value. If a NULL value is specified for the @DateToCheck parameter, set the parameter value to the current date and time by using the GETDATE function.

The procedure should retrieve the same columns as for GetDiscounts but should filter the rows based on the @Category and @DateToCheck parameters.

Page 47: 9767407- Implementing Stored Procedures and Functions

Module 7: Implementing Stored Procedures and Functions 7–45

■ Create a stored procedure named AddDiscount within the Sales schema that inserts new records into the Sales.SpecialOffer table. The following table specifies the required parameters for the insert.

The INSERT statement must be protected by appropriate error handling and any errors must be logged in the dbo.ErrorLog table. If the new insert succeeds, the @NewProductID parameter must be updated with the SCOPE_IDENTITY function value. A return value must also indicate success or failure for the insert.

■ Create a scalar user-defined function named GetMaximumDiscountForCategory within the Sales schema that retrieves the maximum discount percentage currently available for a specific category. Create an @Category nvarchar(50) parameter to limit the results based on the category, and use the GETDATE function to limit the rows based on whether the discount is currently available.

■ Create an inline table-valued user-defined function named GetDiscountsForDate within the Sales schema that retrieves the same columns as the GetDiscounts stored procedure. The function accepts an @DateToCheck datetime parameter to filter the discounts based on the provided date. This allows Adventure Works to test what discounts will be available on a specific date.

■ Create a multi-statement table-valued user-defined function named GetDiscountedProducts within the Sales schema that uses a complex query to retrieve products that have a discount. This complex query will be provided to you. The function accepts an @IncludeHistory bit parameter to filter the returned table based on whether the discount history information is required or only the current information is needed. The returned table will include the following definition.

Parameter name Data type (input unless otherwise specified)

@Description nvarchar(255)

@DiscountPct smallmoney

@Type nvarchar(50)

@Category nvarchar(50)

@StartDate datetime

@EndDate datetime

@MinQty int

@MaxQty int

@NewProductID int OUTPUT

Column name Data type

ProductID int

Name nvarchar(50)

ListPrice money

DiscountDescription nvarchar(255)

DiscountPercentage smallmoney

DiscountAmount money

DiscountedPrice money

Page 48: 9767407- Implementing Stored Procedures and Functions

7–46 Module 7: Implementing Stored Procedures and Functions

Additional information When performing database development tasks, it can be helpful to use SQL Server Management Studio to create a SQL Server Scripts project, and use it to document the Transact-SQL code necessary to re-create the solution if necessary.

Use the following procedure to create a SQL Server Scripts project:

1. Open SQL Server Management Studio, connecting to the server you want to manage.

2. On the File menu, point to New, and then click Project.

3. Select the SQL Server Scripts template and enter a suitable name and location for the project. Note that you can create a solution that contains multiple projects, but in many cases a single project per solution is appropriate.

To add a query file to a project:

1. Click New Query on the Project menu, or right-click the Queries folder in Solution Explorer and click New Query. If Solution Explorer is not visible, you can display it by clicking Solution Explorer on the View menu.

2. When prompted, connect to the server on which you want to execute the query. This will add a connection object to the project.

3. Change the name of the query file from the default name (SQLQuery1.sql) by right-clicking it in Solution Explorer and clicking Rename.

Although you can perform all database development tasks by executing Transact-SQL statements, it is often easier to use the graphical user interface in SQL Server Management Studio. However, you should generate the corresponding Transact-SQL scripts and save them in the project for future reference.

Often, you can generate the Transact-SQL script for an action before clicking OK in the Properties dialog box used to perform the action. Many Properties dialog boxes include a Script drop-down list with which you can script the action to a new query window, a file, the Clipboard, or a SQL Server Agent job. A common technique is to add a blank query file to a project, and then script each action to the Clipboard as it is performed and paste the generated script into the query file.

You can also generate scripts for many existing objects, such as databases and tables. To generate a script, right-click the object in Object Explorer and script the CREATE action. If Object Explorer is not visible, you can display it by clicking Object Explorer on the View menu.

Preparation Ensure that virtual machine 2779A-MIA-SQL-07 is running and that you are logged on as Student.

If a virtual machine has not been started, perform the following steps:

1. Close any other running virtual machines.

2. Start the virtual machine.

3. In the Log On to Windows dialog box, complete the logon procedure by using the user name Student and the password Pa$$w0rd.

Page 49: 9767407- Implementing Stored Procedures and Functions

Module 7: Implementing Stored Procedures and Functions 7–47

Exercise 1: Creating Stored ProceduresCreating the GetDiscounts, GetDiscountsForCategory, GetDiscountsForCategoryAndDate, and AddDiscount stored procedures

Task Supporting information

Create and test the GetDiscounts stored procedure.

1. Open SQL Server Management Studio. Connect to MIAMI when prompted.

2. Open the AWProgrammability.ssmssln solution in D:\Labfiles\Starter.

3. Open the InitializeData.sql query file, and then execute it, confirming that no errors occur.

4. Open the StoredProcedures.sql query file.

5. Create the Sales.GetDiscounts stored procedure according to the requirements, and then execute your CREATE PROCEDURE statement, confirming that no errors occur.

6. Test the Sales.GetDiscounts stored procedure, and then review the results.

Create and test the GetDiscountsForCategory stored procedure.

1. Create the Sales.GetDiscountsForCategory stored procedure according to the requirements, and then execute your CREATE PROCEDURE statement, confirming that no errors occur.

2. Test the Sales.GetDiscountsForCategory stored procedure using 'Reseller' for the @Category value, and then review the results.

Create and test the GetDiscountsForCategoryAndDate stored procedure.

1. Create the Sales.GetDiscountsForCategoryAndDate stored procedure according to the requirements, and then execute your CREATE PROCEDURE statement, confirming that no errors occur.

2. Test the Sales.GetDiscountsForCategoryAndDate stored procedure using 'Reseller' for the @Category value and the default value for the @DateToCheck parameter. Review the results.

3. Test the Sales.GetDiscountsForCategoryAndDate stored procedure using 'Reseller' for the @Category value and a date one month from now for the @DateToCheck value. Review the results.

Page 50: 9767407- Implementing Stored Procedures and Functions

7–48 Module 7: Implementing Stored Procedures and Functions

Create and test the AddDiscount stored procedure.

1. Create the Sales.AddDiscount stored procedure according to the requirements, and then execute your CREATE PROCEDURE statement, confirming that no errors occur.

2. Test the Sales.AddDiscount stored procedure by using the following parameter values.

Parameter Value @Description 'Half price of everything' @DiscountPct .5 @Type 'Seasonal Discount' @Category 'Customer' @StartDate Local variable with

current date from the GETDATE function

@EndDate Local variable with date one month from current date

@MinQty0 @MaxQty20

3. Confirm that a new special offer was created by displaying the @NewProductID OUTPUT parameter value.

4. Copy the previous test, and change the @DiscountPct value to –0.5. Use the return value from the stored procedure to determine whether the insert succeeded or failed. If the insert failed, select the latest record from the dbo.ErrorLog table to confirm the error.

Modify the execution context of the AddDiscount stored procedure.

1. Modify the Sales.AddDiscount stored procedure to execute as Adam, and then execute your ALTER PROCEDURE statement, confirming no errors occur.

2. Test the Sales.AddDiscount stored procedure by using the following parameter values.

Parameter Value@Description 'Half price of everything' @DiscountPct -0.5 @Type 'Seasonal Discount' @Category 'Customer' @StartDate Local variable with

current date from GETDATE function

@EndDate Local variable with date one month from current date

@MinQty 0 @MaxQty 20

3. When the insert fails, select the latest record in the dbo.ErrorLog table to confirm that the UserName is now logged as Adam instead of the dbo account.

Task Supporting information

Page 51: 9767407- Implementing Stored Procedures and Functions

Module 7: Implementing Stored Procedures and Functions 7–49

Exercise 2: Creating FunctionsCreating the GetMaximumDiscountForCategory, GetDiscountsForDate, and GetDiscountedProducts functions

Results checklist Use the following checklist of results to verify whether you have successfully performed this lab:

■ Created a stored procedure named Sales.GetDiscounts

■ Created a stored procedure named Sales.GetDiscountsForCategory

■ Created a stored procedure named Sales.GetDiscountsForCategoryAndDate

■ Created a stored procedure named Sales.AddDiscount

■ Created a user-defined function named Sales.GetMaximumDiscountForCategory

■ Created a user-defined function named Sales.GetDiscountsForDate

■ Created a user-defined function named Sales.GetDiscountedProducts

Task Supporting information

Create and test the GetMaximumDiscountForCategory user-defined function.

1. Open the UserDefinedFunctions.sql query file.

2. Create the Sales.GetMaximumDiscountForCategory scalar function according to the requirements, and then execute your CREATE FUNCTION statement, confirming that no errors occur.

3. Test the Sales.GetMaximumDiscountForCategory scalar function, and then review the results.

Create and test the GetDiscountsForDate user-defined function.

1. Create the Sales.GetDiscountsForDate inline table-valued function according to the requirements, and then execute your CREATE FUNCTION statement, confirming that no errors occur.

2. Test the Sales.GetDiscountsForDate inline table-valued function, and then review the results.

Create and test the GetDiscountedProducts user-defined function.

1. Create the Sales.GetDiscountedProducts multi-statement table-valued function according to the requirements, and then execute your CREATE FUNCTION statement, confirming that no errors occur.

2. Test the Sales.GetDiscountedProducts multi-statement table-valued function, and then review the results.

Page 52: 9767407- Implementing Stored Procedures and Functions