1. Trang chủ
  2. » Công Nghệ Thông Tin

Hướng dẫn học Microsoft SQL Server 2008 part 66 docx

10 303 0
Tài liệu đã được kiểm tra trùng lặp

Đang tải... (xem toàn văn)

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 10
Dung lượng 602,87 KB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

For the purpose of the following code, assume that a linked server connection has been established to the local server with the nameNOLI: SELECT * FROM OpenQuery MAUINOLI, ‘EXEC OBXKites

Trang 1

Because the result set of the stored procedure is returned via a function being used by a data source in

theFROMclause of theSELECTstatement, aWHEREclause can further reduce the output of the stored

procedure

While this technique enables the use of stored procedures within aSELECTstatement, it’s not as

opti-mized as the technique of passing any row restrictions to the stored procedure for processing within the

stored procedure The only benefit of usingopenquery()is that it enables a complex stored procedure

to be called from within an ad hoc query

For the purpose of the following code, assume that a linked server connection has been established to

the local server with the nameNOLI:

SELECT * FROM OpenQuery(

MAUINOLI,

‘EXEC OBXKites.dbo.pProductCategory_Fetch;’) WHERE ProductCategoryDescription Like ‘%stuff%’;

Result:

ProductCategoryName ProductCategoryDescription -

Best Practice

If you need to call complex code within a SELECT statement, using openquery() to call a stored

procedure works, but the syntax is a bit bizarre A better method is to use a CASE expression or create a

user-defined function

Executing remote stored procedures

Two methods exist for calling a stored procedure located on another server: a four-part name reference

and a distributed query Both methods require that the remote server be a linked server Stored

proce-dures may only be called remotely; they may not be created remotely.

The remote stored procedure may be executed by means of the four-part name:

server.database.schma.procedurename

For example, the following code adds a new product category to theOBXKitesdatabase on Noli’s (my

development server) second instance of SQL Server:

EXEC [MAUINoli\SQL2COPENHAGEN].OBXKites.dbo.pProductCategory_AddNew

‘Food’, ‘Eatables’;

Trang 2

Alternately, theOpenQuery()function can be used to call a remote stored procedure:

OpenQuery(linked server name, ‘exec ‘EXEC stored procedure;’)

The next code sample executes thepCustomerType_Fetchstored procedure in the default database

for the user login being used to connect toMAUI\COPENHAGENNoli\SQL2 If the default database is

incorrect, a three-part name can be used to point to the correct database

SELECT CustomerTypeName, DiscountPercent, [Default]

FROM OPENQUERY(

[MAUI\COPENHAGENNoli\SQL2], ‘EXEC OBXKites.dbo.pCustomerType_Fetch;’);

Result:

CustomerTypeName DiscountPercent Default

- -

As with any other distributed query, the Distributed Transaction Coordinator service must be running if

the transaction updates data in more than one server

Passing Data to Stored Procedures

A stored procedure is more useful when it can be manipulated by parameters TheCategoryList

stored procedure created previously returns all the product categories, but a procedure that performs a

task on an individual row requires a method for passing the row ID to the procedure

SQL Server stored procedures may have numerous input and output parameters (SQL Server 2005

increased the number of parameters from 1,024 to 2,100 to be exact)

Input parameters

You can add input parameters that pass data to the stored procedure by listing the parameters after the

procedure name in theCREATE PROCEDUREcommand Each parameter must begin with an@sign,

and becomes a local variable within the procedure Like local variables, the parameters must be defined

with valid data types When the stored procedure is called, the parameter must be included (unless the

parameter has a default value)

The following code sample creates a stored procedure that returns a single product category The

@CategoryNameparameter can accept Unicode character input up to 35 characters in length

The value passed by means of the parameter is available within the stored procedure as the variable

@CategoryNamein theWHEREclause:

USE OBXKites;

Trang 3

go CREATE PROCEDURE dbo.CategoryGet (

@CategoryName NVARCHAR(35) )

AS SELECT ProductCategoryName, ProductCategoryDescription FROM dbo.ProductCategory

WHERE ProductCategoryName = @CategoryName;

go When the following code sample is executed, the Unicode string literal ‘Kite’is passed to the stored

procedure and substituted for the variable in theWHEREclause:

EXEC dbo.CategoryGet N’Kite’;

Result:

ProductCategoryName ProductCategoryDescription -

stunt, to Chinese, to novelty kites

If multiple parameters are involved, the parameter name can be specified in any order, or the

parame-ter values listed in order If the two methods are mixed, then as soon as the parameparame-ter is provided by

name, all the following parameters must be as well

The next four examples each demonstrate calling a stored procedure and passing the parameters by

original position and by name:

EXEC Schema.StoredProcedure

@Parameter1 = n,

@Parameter2 = ‘n’;

EXEC Schema.StoredProcedure

@Parameter2 = ‘n’,

@Parameter1 = n;

EXEC Schema.StoredProcedure n, ‘n’;

EXEC Schema.StoredProcedure n, @Parameter2 = ‘n’;

Parameter defaults

You must supply every parameter when calling a stored procedure, unless that parameter has been

cre-ated with a default value You establish the default by appending an equal sign and the default to the

parameter, as follows:

CREATE PROCEDURE Schema.StoredProcedure (

@Variable DataType = DefaultValue )

Trang 4

The following code, extracted from theOBXKitessample database, demonstrates a stored procedure

default If a product category name is passed in this stored procedure, the stored procedure returns only

the selected product category However, if nothing is passed, theNULLdefault is used in theWHERE

clause to return all the product categories:

CREATE PROCEDURE dbo.pProductCategory_Fetch2

@Search NVARCHAR(50) = NULL

If @Search = null then return all ProductCategories

If @Search is value then try to find by Name

AS

SET NOCOUNT ON;

SELECT ProductCategoryName, ProductCategoryDescription

FROM dbo.ProductCategory

WHERE ProductCategoryName = @Search

OR @Search IS NULL;

IF @@RowCount = 0

BEGIN;

RAISERROR(

‘Product Category ‘’%s" Not Found.’,14,1,@Search);

END;

The first execution passes a product category:

EXEC dbo.pProductCategory_Fetch2 ‘OBX’;

Result:

ProductCategoryName ProductCategoryDescription

-

WhenpProductCategory_Fetchexecutes without a parameter, the@Searchparameter’s default of

NULLallows theWHEREclause to evaluate to true for every row, as follows:

EXEC dbo.pProductCategory_Fetch2;

Result:

ProductCategoryName ProductCategoryDescription

-

stunt, to Chinese, to novelty kites

and Outer Banks videos

Trang 5

Table-valued parameters

New to SQL Server 2008 are table-valued parameters (TVPs) The basic idea is that a table can be created

and populated in the client application or T-SQL and then passed, as a table variable, into a stored

pro-cedure or user-defined function This is no small thing Chapter 1, ‘‘The World of SQL Server,’’ listed

TVPs as my favorite new feature for developers and the number two top new feature overall

In every complex application I’ve worked on, there’s been a requirement that a complex transaction be

passed to the database — orders and order details, flights and flight legs, or an object and a dynamic set

of attributes In each case, the complete transaction includes multiple types of items

Without considering TVPs, there are three traditional ways to solve the problem of how to pass multiple

types of items in a transaction to SQL Server — none of them particularly elegant:

■ Pass each item in a separate stored procedure call —AddNewOrder,AddNewOrder Details— repeatedly for every item, and thenCloseNewOrder This method has two primary problems First, it’s very chatty, with multiple trips to the server Second, if the client does not complete the transaction, a process on the server must clean up the remains of the unfinished transaction

■ Package the entire transaction at the client into XML, pass the XML to SQL Server, and shred the XML into the relational tables This solution is significantly cleaner than the first method, but there’s still the extra work of shredding the data in the server

■ Concatenate any data that includes multiple rows into a comma-delimited string and pass that

as avarchar(max)parameter into the stored procedure Like the XML solution, this method does achieve a single stored procedure call for the complex transaction, but it involves even more coding complexity than the XML method and will prove to be difficult to maintain

Table-valued parameters provide a fourth alternative A table can be created in ADO.NET 3.5 or in

T-SQL and passed into a SQL Server stored procedure or user-defined function

The following script creates a test order, order detail scenario:

USE tempdb;

Create Table dbo.Orders(

OrderID INT NOT NULL IDENTITY Constraint OrdersPK Primary Key, OrderDate DateTime,

CustomerID INT );

Create Table dbo.OrderDetails(

OrderID INT NOT NULL Constraint OrderDetailsFKOrders References Orders, LineNumber SmallInt NOT NULL,

ProductID INT );

the XML solution (not printed here) and the TVP solution (listed here).

Trang 6

The first step is to define a table type in SQL Server for consistency when creating the TVP:

CREATE TYPE OrderDetailsType AS Table (

LineNumber INT,

ProductID INT,

IsNew BIT,

IsDirty BIT,

IsDeleted BIT

);

Once the table type is created, it can be seen in Object Explorer in the Database➪ Programmability ➪

Types➪ User-Defined Table Types node

With the table type established, the stored procedure can now be created that references the table type

The table must be defined as the table type name with theREADONLYoption The TVP parameter will

look like a table variable inside the stored procedure

Code can reference the data as a normal other data source except that it’s read-only Some have

criticized this as a major drawback I don’t see it that way If I want to modify the data and return it, I

think the best way is to return the data as a selected result set

Here’s the stored procedure It simply returns the data from the TVP so it’s easy to see the TVP

in action:

CREATE

alter

PROC OrderTransactionUpdateTVP (

@OrderID INT OUTPUT,

@CustomerID INT,

@OrderDate DateTime,

@Details as OrderDetailsType READONLY

)

AS

SET NoCount ON ;

Begin Try

Begin Transaction;

If @OrderID is NULL then it’s a new order, so Insert Order

If @OrderID IS NULL

BEGIN;

Insert Orders(OrderDate, CustomerID)

Values (@OrderDate, @CustomerID);

Get OrderID value from insert SET @OrderID = Scope_Identity();

END;

Test view of the data

SELECT * FROM @Details ;

Commit Transaction;

End Try

Trang 7

Begin Catch;

RollBack;

End Catch RETURN;

To test table-valued parameters, the following script creates a table variable as the previously defined

table type, populates it using the new row constructers, and then calls the stored procedure:

Declare @OrderID INT;

DECLARE @DetailsTVP as OrderDetailsType;

INSERT @DetailsTVP (LineNumber,ProductID,IsNew,IsDirty,IsDeleted) VALUES

(5, 101, -1, -1, 0), (2, 999, 0, -1, 0), (3, null, 0, 0, 0);

exec OrderTransactionUpdateTVP

@OrderID = @OrderID Output ,

@CustomerID = ‘78’,

@OrderDate = ‘2008/07/24’,

@Details = @DetailsTVP;

Result:

LineNumber ProductID IsNew IsDirty IsDeleted - -

I’ve already converted some of my software to TVP and have found that not only does the TVP syntax

make sense and simplify a nasty problem with an elegant solution, but TVPs are fast Under the

cov-ers, TVPs leverage SQL Server’s bulk insert technology, which is by far the fastest way to move data into

SQL Server

Returning Data from Stored Procedures

SQL Server provides five means of returning data from a stored procedure A batch can return data via

aSELECTstatement or aRAISERRORcommand Stored procedures inherit these from batches and add

output variables and theRETURNcommand And, the calling stored procedure can create a table that

the called stored procedure populates

This section walks through the methods added by stored procedures and clarifies their scope and

purpose

Trang 8

Output parameters

Output parameters enable a stored procedure to return data to the calling client procedure The

key-wordOUTPUTis required both when the procedure is created and when it is called Within the stored

procedure, the output parameter appears as a local variable In the calling procedure or batch, a

vari-able must have been created to receive the output parameter When the stored procedure concludes, its

current value is passed to the calling procedure’s local variable

Although output parameters are typically used solely for output, they are actually two-way parameters

Best Practice

Output parameters are useful for returning single units of data when a whole record set is not required

For returning a single row of information, using output parameters is blazingly faster than preparing a

record set

The next code sample uses an output parameter to return the product name for a given product code

from theProducttable in theOBXKitessample database To set up for the output parameter:

1 The batch declares the local variable@ProdNameto receive the output parameter

2 The batch calls the stored procedure, using@ProdNamein theEXECcall to the stored

procedure

3 Within the stored procedure, the@ProductNameoutput parameter/local variable is created in

the header of the stored procedure The initial value isNULLuntil it is initialized by code

4 Inside the stored procedure, theSELECTstatement sets@ProductNameto ‘Basic Box Kite

21 inch’, the product name for the product code ‘1001’

5 The stored procedure finishes and execution is passed back to the calling batch The value is

transferred to the batch’s local variable,@ProdName

6 The calling batch uses thePRINTcommand to send@ProdNameto the user

This is the stored procedure:

USE OBXKites;

go

CREATE PROC dbo.GetProductName (

@ProductCode CHAR(10),

@ProductName VARCHAR(25) OUTPUT

)

AS

SELECT @ProductName = ProductName

FROM dbo.Product

WHERE Code = @ProductCode;

RETURN;

Trang 9

This is the calling batch:

USE OBXKites;

DECLARE @ProdName VARCHAR(25);

EXEC dbo.GetProductName ‘1001’, @ProdName OUTPUT;

PRINT @ProdName;

Result:

Basic Box Kite 21 inch

Unit Testing

Icombine agile development with unit testing when designing and developing a database, using three

scripts:

Create: The first script includes all the DDL code and creates the database, tables, and

all stored procedures and functions

Sample: The second script includes the sample data in the form of INSERT VALUES

statements and is used to load the data for unit testing

ProcTest: The last script executes every procedure, checking the output against what is

expected from the sample data

Sequentially executing the three scripts unit tests every procedure

Using the Return Command

ARETURNcommand unconditionally terminates the procedure and returns an integer value to the

call-ing batch or client Technically, a return can be used with any batch, but it can only return a value from

a stored procedure or a function

When calling a stored procedure, theEXECcommand must use a local integer variable if the returned

status value is to be captured:

EXEC @LocalVariable = StoredProcedureName;

I’ve seen stored procedures in production at different companies that use the return code for everything

from success/failure, to the number of rows processed, to the@@errorcode Personally, I prefer to use

the return code for success/failure, and pass back any other data in parameters, orRAISERROR The

most important consideration is that the database is 100% consistent in the use ofRETURN

The following basic stored procedure returns a success or failure status, depending on the parameter:

Trang 10

CREATE PROC dbo.IsItOK (

@OK VARCHAR(10)

)

AS

IF @OK = ‘OK’

BEGIN;

RETURN 0;

END;

ELSE

BEGIN;

RETURN -100;

END;

The calling batch:

DECLARE @ReturnCode INT;

EXEC @ReturnCode = dbo.IsItOK ‘OK’;

PRINT @ReturnCode;

EXEC @ReturnCode = dbo.IsItOK ‘NotOK’;

PRINT @ReturnCode;

Result:

0

-100

Path and scope of returning data

Any stored procedure has five possible methods of returning data (SELECT,RAISERROR, external

table,OUTPUTparameters, andRETURN) Deciding which method is right for a given stored procedure

depends on the quantity and purpose of the data to be returned, and the scope of the method used to

return the data The return scope for the five methods is as follows:

■ Selected record sets are passed to the calling stored procedure If the calling stored procedure

consumes the result set (e.g.,INSERT .EXEC) then the result set ends there If the calling

stored procedure does not consume the result set, then it is passed up to the next calling

stored procedure or client

■ RETURNvalues, andOUTPUTparameters are all passed to local variables in the immediate

calling procedure or batch within SQL Server

■ RAISERRORis passed to the calling stored procedure and will continue to bubble up until it

is trapped by aTRY .CATCHor it reaches the client application

If SQL Server Management Studio (the client application) executes a batch that calls stored procedure A,

which then calls stored procedure B, there are multiple ways procedure B can pass data back to

proce-dure A or to the client application, as illustrated in Figure 24-2

Ngày đăng: 04/07/2014, 09:20

TỪ KHÓA LIÊN QUAN