So far, you have used parameters to send data to the procedure. Now you will learn to return data from the procedure using an output parameter. We'll write a procedure, prGetCustomerCart, to return the Order ID for a shopping cart if one exists, or create a shopping cart if one doesn't exist. Then we'll call the prGetCustomerCart from inside the prAddItemToCart procedure and use an output parameter to pass the value back to the calling procedure.
Let's be clear on the logic for prGetCustomerCart. You pass it as a Customer ID and it returns an Order ID. To find the Order ID, it finds an open order for the customer (if one exists), or it creates a new open order. Listing 15.6 shows the completed prGetCustomerCart procedure.
There are a couple of key points in the CREATE syntax. First, the parameter declaration in line 3 includes the keyword OUTPUT. In order to get a variable value to return to the user, you need to declare it with OUTPUT . (Note that if you declare a parameter for OUTPUT, it can still be used to accept values.)
Second, to actually output the variable, you don't need to do anything special. Just assign it a value as in line 35 and the value is passed back to the calling program.
You can test the procedure directly from a SQL batch. You need to provide a local variable as a parameter in order to provide a container for returning the OrderID. The following code shows you how to use the stored procedure that was created and how to check the @ret value to see if the stored procedure worked.
declare @ret int declare @MyCustomerID nchar(5) declare @MyOrderID int select @MyCustomerID = 'QUICK' exec @ret = prGetCustomerCart @MyCustomerID, @MyOrderID output if @ret = 0 print 'The cart for '+ @MyCustomerID + 'is: ' + cast(@MyOrderID as nchar(5)) else print 'Error' The cart for QUICK is: 11078
When SQL Server executes the procedure, it retrieves the OrderID for CustomerID 'QUICK' and puts it into the @OrderID parameter. When the procedure returns, the value is assigned to the variable @MyOrderID by position.
Notice that the keyword, OUTPUT, is also included in the execution string. Both the procedure programmer and the user need to include OUTPUT in order for the value to be returned.
When we say that stored procedures communicate with each other, we really mean that stored procedures pass parameter values back and forth to each other. Now we can create the prAddItemToCustomerCart procedure. Instead of taking an OrderID for a parameter, the procedure accepts a CustomerID. Then it uses the prGetCustomerCart procedure to retrieve the active OrderID for the order detail insert. Listing 15.7 shows how this is done.
There is not a lot of new material here. Perhaps the most important point is how important it is to check the return status of the inner procedure (prGetCustomerCart) lines 13 through 21, before going ahead with the insert. If you don't check the value, you could end up trying to insert a null or incorrect value for OrderID in Order Details.
Output parameters enable two-way communication between a stored procedure on one server (a local server) and a procedure on another server (a remote server).
For example, what if the Order Details table was stored on a local server, but the Orders table was on a remote server? In that case, the user or application would execute the prAddItemToCustomerCart procedure locally. When the procedure ran, it would call the prGetCustomerCart proc remotely, passing in a CustomerID and retrieving an OrderID. The OrderID would be returned as an output parameter.
Here's the crucial point: The results of a SELECT statement in a remote procedure are returned directly to the calling program (that is, the client application). The output parameter is the only method of returning a value to the calling procedure or batch; that value could be put to use immediately.
To invoke a remote procedure, fully qualify the procedure name when it is called. In this case, the name includes the server name as well as database, owner, and object name. In Listing 15.7, we invoked the prGetCustomerCart procedure locally. To invoke the prGetCustomerCart procedure on another server, you would replace the execute statement in line 13 (leaving the parameters in lines 14 and 15) with the following statement:
execute @ret = OrderServer.Northwind.Northwind_DBO.prGetCustomerCart
There are a couple of setup and security issues to be resolved to implement remote procedures, but when they are implemented, the Remote Procedure Call (or RPC) mechanism provides a fast and reliable cross-server communications method.