IBM Books

Embedded SQL Programming Guide


Writing Stored Procedures on DB2

An application using stored procedures must be written in two separate procedures. The calling procedure is contained in a client application, and executes on the client. It can be written in any of the supported host languages. The stored procedure executes at the location of the database on the database server, and must be written in one of the supported languages for that database server.

The two procedures must be built in separate steps.

The client application performs the following:

  1. Declares, allocates, and initializes storage for the optional data structures and host variables.
  2. Connects to a database. (It does this by executing the CONNECT TO statement, or by doing an implicit connect. See the SQL Reference for details.)
  3. Executes on the client.
  4. Invokes the stored procedure through the SQL CALL statement.
  5. Performs a COMMIT or ROLLBACK to the database.
  6. The application disconnects from the database.

Note that you can code SQL statements in any of the above steps.

When invoked, the stored procedure performs the following:

  1. Accepts the SQLDA data structure from the client application. (Host variables are passed through an SQLDA data structure generated by the database manager when the SQL CALL statement is executed.)
  2. Executes on the database server under the same transaction as the client application.
  3. Returns SQLCA information and optional output data to the client application.

The stored procedure executes when called by the client application. Control is returned to the client when the server procedure finishes processing. You can take several stored procedures and put them into one library.

Client Application

The client application performs several steps before calling the stored procedure. It must be connected to a database, and it must declare, allocate, and initialize the SQLDA structure or host variables. The SQL CALL statement can accept a series of host variables, or an SQLDA structure. (See the SQL Reference for a description of the SQL CALL statement.)
Note:Do not allocate storage for these structures on the database server. The database manager automatically allocates duplicate storage based upon the storage allocated by the client application. Do not alter any storage pointers for the input/output parameters on the stored procedure side. Attempting to replace a pointer with a locally created storage pointer will cause an error with SQLCODE -1133 (SQLSTATE 39502).

SQLDA Structure

For the SQLDA structure used, perform the following steps before calling the stored procedure:

  1. Allocate storage for the structure with the desired number of base SQLVAR elements.

  2. Set the SQLN field to the number of SQLVAR elements allocated.

  3. Set the SQLD field to the number of SQLVAR elements actually used.

  4. Initialize each SQLVAR element used as follows:

If your application will be working with character strings defined as FOR BIT DATA, you will need to initialize the SQLDAID field to indicate that the SQLDA includes FOR BIT DATA definitions and the SQLNAME field of each SQLVAR that defines a FOR BIT DATA element. If your application will be working with large objects, that is, data with types of CLOB, BLOB, or DBCLOB, you will also need to initialize the secondary SQLVAR elements. See the information on the SQLDA structure in the SQL Reference.

Allocating Host Variables

Following are the steps to allocate the necessary input host variables on the client side of a stored procedure:

When writing the client portion of your stored procedure, you should attempt to overload as many of the SQLVARs as possible in order to increase the efficiency of handling SQLVARs. For example, when returning an SQLCODE to the client from the stored procedure, try to use an input SQLVAR that is declared as an INTEGER to return the SQLCODE. Unless you need to reuse the values in the SQLDA on the client, there is no problem overwriting the content of any SQLDA buffer.

In addition, the client application should set the indicator of output-only SQLVARs to -1 as discussed in "Data Structure Manipulation". This will improve the performance of the parameter passing mechanism by avoiding having to pass the contents of the SQLDATA pointer as only the indicator is sent. You should set the SQLTYPE field to a nullable data type for these parameters. If the SQLTYPE indicates a non-nullable data type, the indicator variable is not checked by the database manager.

Running the Client Application

The client application must ensure that a database connection has been made before invoking the stored procedure, or an error is returned. After the database connection and data structure initialization, the client application calls the stored procedure and passes any required data. The application disconnects from the database. Note that you can code SQL statements in any of the above steps.

Stored Procedure

The stored procedure is invoked by the SQL CALL statement and executes using data passed to it by the client application. Information is returned to the client application using the stored procedure's SQLDA structure.

The parameters of the SQL CALL statement are treated as both input and output parameters and are converted into the following format for the stored procedure:

     SQL_API_RC SQL_API_FN proc_name( void *reserved1,
                                      void *reserved2,
                                      struct sqlda *inoutsqlda, 
                                      struct sqlca *sqlca )

The SQL_API_FN is a macro that specifies the calling convention for a function that may vary across each supported operating system. This macro is required when you write stored procedures or UDFs.

Following is an example of how a CALL statement maps to a server's parameter list:

     CALL OUTSRV (:empno:empind,:salary:salind)

The parameters to this call are converted into an SQLDA structure with two SQLVARs. The first SQLVAR points to the empno host variable and the empind indicator variable. The second SQLVAR points to the salary host variable and the salind indicator variable.

Notes:

  1. The SQLDA structure is not passed to the stored procedure if the number of elements, SQLD, is set to 0. In this case, if the SQLDA is not passed, the stored procedure receives a NULL pointer.

  2. You cannot execute any connection-related statements or commands, such as, CONNECT, CONNECT TO, CONNECT RESET, CREATE DATABASE, DROP DATABASE, BACKUP, RESTORE, or FORWARD RECOVERY in a stored procedure.

  3. Stored procedures run in the background, so you cannot write to the screen. However, you can write to a file.

  4. Stored procedures cannot contain commands that would terminate the current process. A stored procedure should always return control to the client without terminating the current process.

  5. The values of all environment variables beginning with 'DB2' are captured at the time the database manager is started with db2start, and are available in all stored procedures whether or not they are fenced. The only exception is the DB2CKPTR environment variable. Note that the environment variables are captured; any changes to the environment variables after db2start is issued are not passed to the stored procedures.

  6. On UNIX-based systems, your stored procedure runs under the UID of the DB2 Agent Process (NOT FENCED), or the UID which owns the db2dari executable (FENCED). This UID controls the system resources available to the stored procedure. For information on the db2dari executable, see the Quick Beginnings book for your platform.

Data Structure Manipulation

The database manager automatically allocates a duplicate SQLDA structure at the database server. To reduce network traffic, it is important to indicate which host variables are input-only, and which ones are output-only. The client procedure should set the indicator of output-only SQLVARs to -1. The server procedure should set the indicator for input-only SQLVARs to -128. This allows the database manager to choose which SQLVARs are passed.

Note that an indicator variable is not reset if the client or the server sets it to a negative value (indicating that the SQLVAR should not be passed). If the host variable to which the SQLVAR refers is given a value in the stored procedure or the client code, its indicator variable should be set to zero or a positive value so that the value is passed. For example, consider a stored procedure which takes one output-only parameter, called as follows:

     empind = -1; 
     EXEC SQL CALL storproc(:empno:empind);

When the stored procedure sets the value for the first SQLVAR, it should also set the value of the indicator to a non-negative value so that the result is passed back to empno.

Input/Output SQLDA and SQLCA Structures

The stored procedure runs using any information passed in the input variables of the SQLDA structure. Information is returned to the client in the output variables of the SQLDA. Do not change the value of the SQLD, SQLTYPE, and SQLLEN fields of the SQLDA, as these fields are compared to the original values set by the client application before data is returned. If they are different, one of the following SQLCODEs is returned:

SQLCODE -1113 (SQLSTATE 39502)
The data type of a variable (that is, the value in SQLTYPE) has changed.
SQLCODE -1114 (SQLSTATE 39502)
The length of a variable (that is, the value in SQLLEN) has changed.
SQLCODE -1115 (SQLSTATE 39502)
The SQLD field has changed.

In addition, do not change the pointer for the SQLDATA and the SQLIND fields, although you can change the value that is pointed to by these fields.
Note:It is possible to use the same variable for both input and output.

Before the stored procedure returns, SQLCA information should be explicitly copied to the SQLCA parameter of the stored procedure.

Return Values

The return value of the stored procedure is never returned to the client application. It is used by the database manager to determine if the server procedure should be released from memory upon exit.

The stored procedure returns with one of the following values:

SQLZ_DISCONNECT_PROC
Tells the database manager to release (unload) the library.

SQLZ_HOLD_PROC
Tells the database manager to keep the server library in main memory so that the library will be ready for the next invocation of the stored procedure. This may lead to better performance.

If the stored procedure is invoked only once, SQLZ_DISCONNECT_PROC should be returned.

If the client application issues multiple calls to invoke the same stored procedure, SQLZ_HOLD_PROC should be the return value of the stored procedure. The stored procedure will not be unloaded.

If SQLZ_HOLD_PROC is used, the last invocation of the server request should return the value SQLZ_DISCONNECT_PROC to free the server library from main memory. Otherwise, the library remains in main memory until the database manager is stopped. As an alert to the server, the client application could pass a flag in one of the parameters indicating the final call.

Code Page Considerations

The code page considerations depend on the server.

When a client program (using, for example, code page A) calls a remote stored procedure that accesses a database using a different code page (for example, code page Z), the following events occur:

  1. Input character string parameters (whether defined as host variables or in an SQLDA in the client application) are converted from the application code page (A) to the one associated with the database (Z). Conversion does not occur for data defined in the SQLDA as FOR BIT DATA(4)

  2. Once the input parameters are converted, the database manager does not perform any more code page conversions.

    Therefore, you must run the stored procedure using the same code page as the database, in this example, code page Z. It is a good practice to prep, compile, and bind the server procedure using the same code page as the database.

  3. When the stored procedure finishes, the database manager converts the output character string parameters (whether defined as host variables or in an SQLDA in the client application) and the SQLCA character fields from the database code page (Z) back to the application code page (A). Conversion does not occur for data defined in the SQLDA as FOR BIT DATA(4).
Note:If the server being accessed is running Version 1 of DB2 for OS/2, the client code page must be the same as the database code page.

For more information on this topic, see "Conversion Between Different Code Pages".

C++ Consideration

When writing a stored procedure in C++, you may want to consider declaring the procedure name as:

     extern "C" SQL_API_RC SQL_API_FN proc_name( reserved1, reserved2,
                                                    inoutsqlda, sqlca )

The extern "C" prevents type decoration (or mangling) of the function name by the C++ compiler. Without this declaration, you have to include all the type decoration for the function name when you call the stored procedure.

Java Considerations

When creating a stored procedure in the Java language, you must use the CREATE PROCEDURE statement to register the procedure to the system catalog table SYSCAT.PROCEDURES. For details on writing stored procedures in Java, see "Java UDFs and Stored Procedures", or refer to the CREATE PROCEDURE statement in the SQL Reference.

Graphic Host Variable Considerations

Any stored procedure written in C or C++, that receives or returns graphic data through its parameter input or output SQLDA should generally be precompiled with the WCHARTYPE NOCONVERT option. This is because graphic data passed through these SQLDAs is considered to be in DBCS format, rather than the wchar_t process code format. Using NOCONVERT means that graphic data manipulated in SQL statements in the stored procedure will also be in DBCS format, matching the format of the parameter data.

With WCHARTYPE NOCONVERT, no character code conversion occurs between the graphic host variable and the database manager. The data in a graphic host variable is sent to, and received from, the database manager as unaltered DBCS characters. Note that if you do not use WCHARTYPE NOCONVERT, it is still possible for you to manipulate graphic data in wchar_t format in a stored procedure; however, you must perform the input and output conversions manually.

CONVERT can be used in fenced stored procedures, and it will affect the graphic data in SQL statements within the stored procedure, but not through the stored procedure's interface. Not-fenced stored procedures must be built using the NOCONVERT option.

In summary, graphic data passed to or returned from a stored procedure through its input or output SQLDA is in DBCS format, regardless of how it was precompiled with the WCHARTYPE option.

For important information on handling graphic data in C applications, see "Handling Graphic Host Variables". For information on EUC code sets and application guidelines, refer to "Japanese and Traditional-Chinese EUC Code Set Considerations", and more specifically to "Considerations for Stored Procedures".

Distributed Unit of Work (DUOW) Consideration

Stored procedures that are called by applications in which the CONNECT TYPE 2 DUOW parameter is in effect, are restricted from issuing COMMIT or ROLLBACK, either dynamically or statically.

Summary of Data Structure Usage

Table 10 summarizes the use of the various structure fields by the stored procedures application. In the table, sqlda is an SQLDA structure passed to the stored procedure and n is a numeric value indicating a specific SQLVAR element of the SQLDA. The numbers on the right refer to the notes following the table.


Table 10. Stored Procedures Parameter Variables
Input/Output SQLDA sqlda.SQLDAID


4





sqlda.SQLDABC


4





sqlda.SQLN
2
4





sqlda.SQLD
2 3
5



Input/Output SQLVAR sqlda.n.SQLTYPE
2 3
5




sqlda.n.SQLLEN
2 3
5




sqlda.n.SQLDATA 1 2 3

6
8

sqlda.n.SQLIND 1 2 3

6
8 9

sqlda.n.SQLNAME.length




6 7


sqlda.n.SQLNAME.data




6 7


sqlda.n.SQLDATATYPE_NAME
2 3
5




sqlda.n.SQLLONGLEN
2 3
5




sqlda.n.SQLDATALEN 1 2 3

6 7

SQLCA (all elements)





6 7

Note:

    Before invoking the stored procedure, the client application must:

  1. Allocate storage for the pointer element based on SQLTYPE and SQLLEN.
  2. Initialize the element with the appropriate data.

    When called by the application, the database manager:

  3. Sends data in the original element to a duplicate element allocated at the stored procedure. The SQLN element is initialized with the data in the SQLD element.

    When invoked, the stored procedure can:

  4. Alter data in the duplicate element. The data can be altered as needed since it is not checked for validity or returned to the client application.

    When the stored procedure terminates, the database manager:

  5. Checks data in the duplicate elements. If the values in these fields do not match the data in the original elements, an error is returned.
  6. Returns data in the duplicate elements to the original element.
  7. The data can be altered as needed since it is not checked for validity.
  8. The data pointed to by the elements can be altered as needed since they are not checked for validity but are returned to the client application.
  9. The SQLIND field is not passed in or out if SQLTYPE indicates the column type is not nullable.


Footnotes:

(4) If the parameter of the stored procedure is defined as FOR BIT DATA at the server, conversion does not occur for a CALL statement to DB2 for MVS/ESA, DB2 for OS/390, or DB2 for AS/400, regardless of whether it is explicitly specified in the SQLDA. (Refer to the section on the SQLDA in the SQL Reference for details.)


[ Top of Page | Previous Page | Next Page | Table of Contents | Index ]

[ DB2 List of Books | Search the DB2 Books ]