IBM Books

Application Development Guide


Writing Stored Procedures

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 by executing the CONNECT TO statement, or by doing an implicit connect. Refer to the SQL Reference for details.
  3. Invokes the stored procedure through the SQL CALL statement.
  4. Issues a COMMIT or ROLLBACK to the database.
  5. 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 parameters from the client application.
  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 put several stored procedures into one library.

This chapter describes how to write stored procedures with the following parameter styles:

GENERAL
The stored procedure receives parameters as host variables from the CALL statement in the client application. The stored procedure does not directly pass null indicators to the client application. GENERAL is the equivalent of SIMPLE stored procedures for DB2 Universal Database for OS/390.

GENERAL WITH NULLS
The stored procedure receives a vector of null indicators for each of the parameters on the CALL. Like GENERAL, parameters are passed as host variables. GENERAL WITH NULLS is the equivalent of SIMPLE WITH NULLS stored procedures for DB2 Universal Database for OS/390.

JAVA
The stored procedure uses a parameter passing convention that conforms to the SQLJ Routines specification. The stored procedure receives IN parameters as host variables, and receives OUT and INOUT parameters as single entry arrays.

You must register each stored procedure for the previously listed parameter styles with a CREATE PROCEDURE statement. The CREATE PROCEDURE statement specifies the procedure name, arguments, location, and parameter style of each stored procedure. These parameter styles offer increased portability and scalability of your stored procedure code across the DB2 family.

For information on using the styles of stored procedures supported by versions of DB2 prior to Version 6, that is, the DB2DARI and DB2GENERAL parameter styles, see Appendix C, DB2DARI and DB2GENERAL Stored Procedures and UDFs.

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 host variables or SQLDA structure. The SQL CALL statement can accept a series of host variables, or an SQLDA structure. Refer to the SQL Reference for descriptions of the SQL CALL statement and the SQLDA structure. For information on using the SQLDA structure in a client application, see Appendix C, DB2DARI and DB2GENERAL Stored Procedures and UDFs.

Allocating Host Variables

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

  1. Declare enough host variables for all input variables that will be passed to the stored procedure.
  2. Determine which input host variables can also be used to return values back from the stored procedure to the client.
  3. Declare host variables for any additional values returned from the stored procedure to the client.

When writing the client portion of your stored procedure, you should attempt to overload as many of the host variables as possible by using them for both input and output. This will increase the efficiency of handling multiple host variables. For example, when returning an SQLCODE to the client from the stored procedure, try to use an input host variable that is declared as an INTEGER to return the SQLCODE.
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).

Calling Stored Procedures

You can invoke a stored procedure stored at the location of the database by using the SQL CALL statement. Refer to the SQL Reference for a complete description of the CALL statement. Using the CALL statement is the recommended method of invoking stored procedures.

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 on the Server

The stored procedure is invoked by the SQL CALL statement and executes using data passed to it by the client application. The parameter style with which you register the stored procedure in the database manager with the CREATE PROCEDURE statement determines how the stored procedure receives data from the client application.

Registering Stored Procedures

To use the CREATE PROCEDURE statement, you must declare the following:

Your CREATE PROCEDURE should also declare the following:

You can find more information on the CREATE PROCEDURE statement, including its full syntax and options for DB2 family compatibility, in the SQL Reference. Descriptions of typical usages of the CREATE PROCEDURE statement follow.

Procedure Names 

You can overload stored procedures only by using the same name for procedures that accept a unique number of parameters. Since DB2 does not distinguish between data types, you cannot overload stored procedures based on parameter data types.

For example, issuing the following CREATE PROCEDURE statements will work because they accept one and two parameters, respectively:

     CREATE PROCEDURE OVERLOAD (IN VAR1 INTEGER) ...
     CREATE PROCEDURE OVERLOAD (IN VAR1 INTEGER, IN VAR2 INTEGER) ...

However, DB2 will fail to register the second stored procedure in the following example because it has the same number of parameters as the first stored procedure with the same name:

     CREATE PROCEDURE OVERLOADFAIL (IN VAR1 INTEGER) ...
     CREATE PROCEDURE OVERLOADFAIL (IN VAR2 VARCHAR(15)) ...

Parameter Modes 

You must declare every parameter passed from a client application to the stored procedure, and from the stored procedure back to the client application, as either an IN, OUT, or INOUT parameter. For each parameter, you must also specify a name and SQL data type. See Variable Declaration and CREATE PROCEDURE Examples for examples.

IN
Passes a value to the stored procedure from the client application, but returns no value to the client application when control returns to the client application

OUT
Stores a value that is passed to the client application when the stored procedure terminates

INOUT
Passes a value to the stored procedure from the client application, and returns a value to the client application when the stored procedure terminates

Location 

The EXTERNAL clause of the CREATE PROCEDURE statement tells the database manager the location of the library that contains the stored procedure. If you do not specify an absolute path for the library, or a jar name for Java stored procedures, the database manager searches the function directory. The function directory is a directory defined for your operating system as follows:

Unix operating systems
sqllib/function

OS/2 or Windows 32-bit operating systems
instance_name\function, where instance_name represents the value of the DB2INSTPROF instance-specific registry setting. If DB2 does not find the stored procedure in instance_name\function, DB2 searches the directories defined by the PATH and LIBPATH environment variables.

For example, the function directory for a Windows NT server with DB2 installed in the C:\sqllib directory, and with no specified DB2INSTPROF registry setting, is:

     C:\sqllib\function
Note:You should give your library a name that is different than the stored procedure name. If DB2 locates the library in the search path, DB2 executes a stored procedure with the same name as its library as a FENCED DB2DARI procedure.

For LANGUAGE C stored procedures, specify:

On a UNIX-based system, for example, mymod!proc8 directs the database manager to the sqllib/function/mymod library and to use entry point proc8 within that library. On Windows 32-bit and OS/2 operating systems mymod!proc8 directs the database manager to load the mymod.dll file from the function directory and call the proc8() procedure in the dynamic link library (DLL).

For LANGUAGE JAVA stored procedures, use:

For example, if you specify MyPackage.MyClass.myMethod, the database manager uses the myMethod method in the MyClass class, within the MyPackage package. Since you did not specify a JAR file, the database manager will search the function directory.

For more information on the function directory, see Location.

LANGUAGE 

For C/C++, declare LANGUAGE C in your CREATE PROCEDURE statement. For Java stored procedures, declare LANGUAGE JAVA. For COBOL stored procedures, declare LANGUAGE COBOL. For Fortran or REXX stored procedures, you must write the stored procedure as a DB2DARI stored procedure. For more information on writing DB2DARI stored procedures, see Appendix C, DB2DARI and DB2GENERAL Stored Procedures and UDFs.

LANGUAGE C
The database manager calls the stored procedure using ANSI C calling and linkage conventions. Use this option for most C/C++ stored procedures.

LANGUAGE JAVA
The database manager calls the stored procedure as a method in a Java class. Use this option for any Java stored procedure.

LANGUAGE COBOL
The database manager calls the stored procedure using COBOL calling and linkage conventions. Use this option for COBOL stored procedures.

PARAMETER STYLEs 

Table 9 summarizes the combinations of PARAMETER STYLE (horizontal axis) and LANGUAGE (vertical axis) allowed in CREATE PROCEDURE statements for DB2 Version 6.

Table 9. CREATE PROCEDURE: Valid Combinations of PARAMETER STYLE and LANGUAGE
  GENERAL, GENERAL WITH NULLS JAVA DB2SQL DB2DARI DB2GENERAL
LANGUAGE C Y N Y Y N
LANGUAGE JAVA N Y N N Y
LANGUAGE COBOL Y N Y N N

GENERAL
The stored procedure receives parameters as host variables from the CALL statement in the client application. The stored procedure does not directly pass null indicators to the client application. You can only use GENERAL when you also specify the LANGUAGE C or LANGUAGE COBOL option.

DB2 Universal Database for OS/390 compatibility note: GENERAL is the equivalent of SIMPLE.

GENERAL WITH NULLS
The stored procedure receives a vector of null indicators for each of the parameters on the CALL. Like GENERAL, parameters are passed as host variables. You can only use GENERAL WITH NULLS when you also specify the LANGUAGE C or LANGUAGE COBOL option.

DB2 Universal Database for OS/390 compatibility note: GENERAL WITH NULLS is the equivalent of SIMPLE WITH NULLS

JAVA
The stored procedure uses a parameter passing convention that conforms to the SQLJ Routines specification. The stored procedure receives IN parameters as host variables, and receives OUT and INOUT parameters as single entry arrays. You can only use JAVA when you also specify the LANGUAGE JAVA option.

DB2SQL
DB2 passes the following arguments to the stored procedure:

You can only specify DB2SQL when you also specify the LANGUAGE C or LANGUAGE COBOL option.

DB2GENERAL
The stored procedure uses a parameter passing convention that is only supported by DB2 Java stored procedures. You can only use DB2GENERAL when you also specify the LANGUAGE JAVA option.

For increased portability, you should write Java stored procedures using the PARAMETER STYLE JAVA conventions. See Appendix C, DB2DARI and DB2GENERAL Stored Procedures and UDFs for more information on writing DB2GENERAL parameter style stored procedures.

DB2DARI
The stored procedure uses a parameter passing convention that conforms with C language calling and linkage conventions. This option is only supported by DB2 Universal Database, and can only be used when you also specify the LANGUAGE C option.

To increase portability across the DB2 family, you should write your LANGUAGE C stored procedures using the GENERAL or GENERAL WITH NULLS parameter styles. If you want to write DB2DARI parameter style stored procedures, see Appendix C, DB2DARI and DB2GENERAL Stored Procedures and UDFs.

Passing a DBINFO Structure 

For LANGUAGE C stored procedures with a PARAMETER TYPE of GENERAL, GENERAL WITH NULLS, or DB2SQL, you have the option of writing your stored procedure to accept an additional parameter. You can specify DBINFO in the CREATE PROCEDURE statement to instruct the client application to pass a DBINFO structure containing information about the DB2 client to the stored procedure, along with the call parameters. The DBINFO structure contains the following values:

Data base name
The name of the database to which the client is connected.

Application authorization ID
The application run-time authorization ID.

Code page
The code page of the database.

Schema name
Not applicable to stored procedures.

Table name
Not applicable to stored procedures.

Column name
Not applicable to stored procedures.

Database version and release
The version, release, and modification level of the database server invoking the stored procedure.

Platform
The platform of the database server.

Table function result column numbers
Not applicable to stored procedures.

For more information on the DBINFO structure, see DBINFO Structure.

Writing Stored Procedures as main Functions 

For LANGUAGE C stored procedures with a PARAMETER TYPE of GENERAL, GENERAL WITH NULLS, or DB2SQL, you have the option of writing your stored procedure to accept parameters like a main function in a C program (MAIN) or like a subroutine (SUB). The default value for PROGRAM TYPE is SUB, which accepts parameters as separate arguments; for example:

    void storproc (int arg1, long arg2, int arg3);

To write a stored procedure that accepts arguments like a main function in a C program, specify PROGRAM TYPE MAIN in the CREATE PROCEDURE statement. You must write stored procedures of PROGRAM TYPE MAIN to conform to the following specifications:

For example, the signature for a stored procedure of PROGRAM TYPE MAIN would appear as follows:

   int main(int argc, char* argv[])

Variable Declaration and CREATE PROCEDURE Examples

The following examples demonstrate the stored procedure source code and CREATE PROCEDURE statements you would use in hypothetical scenarios with the SAMPLE database.

Using IN and OUT Parameters 

Assume that you want to create a Java stored procedure GET_LASTNAME that, given EMPNO (SQL type VARCHAR), returns LASTNAME (SQL type CHAR) from the EMPLOYEE table in the SAMPLE database. You will create the procedure as the getname method of the Java class StoredProcedure, contained in the JAR installed as myJar. Finally, you will call the stored procedure with a client application coded in C.

  1. Declare two host variables in your stored procedure source code:
         String empid;
         String name;
         ...
         #sql { SELECT lastname INTO :empid FROM employee WHERE empno=:empid } 
    

  2. Register the stored procedure with the following CREATE PROCEDURE statement:
      CREATE PROCEDURE GET_LASTNAME (IN EMPID CHAR(6), OUT NAME VARCHAR(15))
          EXTERNAL NAME 'myJar:StoredProcedure.getname'
          LANGUAGE JAVA PARAMETER STYLE JAVA FENCED
          READS SQL DATA
    

  3. Call the stored procedure from your client application written in C:

      EXEC SQL BEGIN DECLARE SECTION;
         struct name { short int; char[15] }
         char[7] empid;
      EXEC SQL END DECLARE SECTION;
         ...
      EXEC SQL CALL GET_LASTNAME (:empid, :name);
    

Using INOUT Parameters 

For the following example, assume that you want to create a C stored procedure GET_MANAGER that, given DEPTNUMB (SQL type SMALLINT), returns MANAGER (SQL type SMALLINT) from the ORG table in the SAMPLE database.

  1. Since DEPTNUMB and MANAGER are both of SQL data type SMALLINT, you can declare a single variable in your stored procedure that receives a value from and returns a value to the client application:
      EXEC SQL BEGIN DECLARE SECTION;
        short onevar = 0;
      EXEC SQL END DECLARE SECTION;
    

  2. Register the stored procedure with the following CREATE PROCEDURE statement:
      CREATE PROCEDURE GET_MANAGER (INOUT ONEVAR SMALLINT)
          EXTERNAL NAME 'stplib!getman'
          LANGUAGE C PARAMETER STYLE GENERAL FENCED
          READS SQL DATA
    

  3. Call the stored procedure from your client application written in Java:
      short onevar = 0;
        ...
      #SQL { CALL GET_MANAGER (:INOUT onevar) };
    

SQL Statements in Stored Procedures

Stored procedures can contain SQL statements. When you issue the CREATE PROCEDURE statement, you should specify the type of SQL statements the stored procedure contains, if any. If you do not specify a value when you register the stored procedure, the database manager uses the restrictive default value CONTAINS SQL. To indicate the type of SQL used in the stored procedure, you can use one of the following four options:

NO SQL
No SQL statements are allowed in the stored procedure. The database manager returns an error if the stored procedure attempts to execute any SQL statement.

CONTAINS SQL
The database manager returns an error if the stored procedure attempts to execute any of the following SQL statements:

READS SQL DATA
The database manager returns an error if the stored procedure attempts to execute any of the following SQL statements:

MODIFIES SQL DATA
The database manager returns an error if the stored procedure attempts to execute any of the following SQL statements:

For more information on the CREATE PROCEDURE statement, refer to the SQL Reference.

Restrictions

When you create a stored procedure, you must observe the following restrictions:

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.
Note:Java stored procedures do not return values to the database manager. This section applies only to stored procedures that are not written in Java.

The stored procedure returns 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 improve performance.

If the stored procedure is invoked only once, it should return SQLZ_DISCONNECT_PROC.

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 stored procedure should return the value SQLZ_DISCONNECT_PROC to free the stored procedure library from main memory. Otherwise, the library remains in main memory until the database manager is stopped. As an alert to the stored procedure, the client application could pass a flag in one of the parameters indicating the final call.

Example OUT Stored Procedure

Following is a sample program demonstrating the use of an OUT host variable. The client application invokes a stored procedure that determines the median salary for employees in the SAMPLE database. (The definition of the median is that half the values lie above it, and half below it.) The median salary is then passed back to the client application using an OUT host variable.

This sample program calculates the median salary of all employees in the SAMPLE database. Since there is no existing SQL column function to calculate medians, the median salary can be found iteratively by the following algorithm:

  1. Determine the number of records, n, in the table.
  2. Order the records based upon salary.
  3. Fetch records until the record in row position n/2+1 is found.
  4. Read the median salary from this record.

An application that uses neither the stored procedures technique, nor blocking cursors, must FETCH each salary across the network as shown in Figure 5.

Figure 5. Median Sample Without a Stored Procedure


Median Sample Without a Stored Procedure

Since only the salary at row n/2+1 is needed, the application discards all the additional data, but only after it is transmitted across the network.

You can design an application using the stored procedures technique that allows the stored procedure to process and discard the unnecessary data, returning only the median salary to the client application. Figure 6 shows this feature.

Figure 6. Median Sample Using a Stored Procedure


Median Sample Using a Stored Procedure

OUT Client Description shows a sample OUT host variable client application and stored procedure. The sample programs are available in Java as:

Client application
Outcli.java

Stored procedure
Outsrv.sqlj

For the OUT host variable client application and stored procedure in other programming languages, refer to the sqllib/samples directory.

OUT Client Description

  1. Include Files. The program begins with the following include files:

    SQL
    Defines the symbol SQL_TYP_FLOAT

    SQLDA
    Defines the descriptor area

    SQLCA
    Defines the communication area for error handling

  2. Connect to Database. The application must connect to the database before registering or invoking the stored procedure.

  3. Register the Stored Procedure. The stored procedure is normally registered outside of the client application, but is included in the client application to demonstrate how to register a stored procedure. The parameter list contains one output (OUT) host variable of type DOUBLE.

  4. Declare and Initialize the Host Variable. This step declares and initializes the host variable. Java programs must register the data type of each parameter before invoking the stored procedure.

  5. Invoke the Stored Procedure. The application invokes the procedure outsrv at the location of the database, sample, using a CALL statement with one host variable.

  6. Disconnect from Database. A Java application automatically disconnects from the database when the application terminates.

The CHECKERR macro/function is an error checking utility which is external to the program. The location of this error checking utility depends upon the programming language used:

C
check_error is redefined as CHECKERR and is located in the util.c file.

Java
Any SQL error is thrown as an SQLException and handled in the catch block of the application.

COBOL
CHECKERR is an external program named checkerr.cbl.

FORTRAN
CHECKERR is a subroutine located in the util.f file.

REXX
CHECKERR is a procedure located at bottom of the current program.

See Using GET ERROR MESSAGE in Example Programs for the source code for this error checking utility.

Example Client Application: Outcli.java

import java.sql.*;              // JDBC classes
 
class Outcli
{   static
  {   try
    {   Class.forName ("COM.ibm.db2.jdbc.app.DB2Driver").newInstance ();
    }
    catch (Exception e)
    {   System.out.println ("\n  Error loading DB2 Driver...\n" + e);
      System.exit(1);
    }
  }
 
  public static void main (String argv[])
  {   try 
    {   System.out.println ("  Java Output Stored Procedure Sample");
      // Connect to Sample database
 
      Connection con = null;
      // URL is jdbc:db2:dbname
      String url = "jdbc:db2:sample";
 
      if (argv.length == 0)  (2)
      {   // connect with default id/password
          con = DriverManager.getConnection(url);
      }
      else if (argv.length == 2)
      {   String userid = argv[0];
        String passwd = argv[1];
 
        // connect with user-provided username and password
        con = DriverManager.getConnection(url, userid, passwd);
      }
      else 
      {   throw new Exception("\nUsage: java Outcli [username password]\n");
      } 
 
      // Set AutoCommit
      con.setAutoCommit(true);
 
      // Register and call the Remote Procedure
 
      String callName = "outsrv";
      String storedProcName = "Outsrv!outputStoredProcedure";
      String mode = "fenced";
 
      Statement stmt = con.createStatement (); // for DROP/CREATE
 
      // drop the stored procedure if it exists
      try
      {   stmt.executeUpdate ("DROP PROCEDURE " + callName);
      }
      catch (Exception e)
      {   // ignore this error
      }
 
      // construct a parameter list for the stored procedure and
      // register it in the system catalogs (3)
      String parameterList = "(out    medianSalary     double)";
 
      System.out.println ("\n  Registering Java stored procedure " 
                    + callName + "\n     as " + storedProcName +
                    "\n     in " + mode + " mode");
 
      stmt.executeUpdate ("CREATE PROCEDURE " + callName + parameterList +
                    " LANGUAGE JAVA " +
                    " PARAMETER STYLE DB2GENERAL " + mode +
                    " EXTERNAL NAME '" + storedProcName + "'");
      stmt.close ();
 
      // prepare the CALL statement
      CallableStatement callableStmt;
      String sql = "Call " + callName + "(?) ";
      callableStmt = con.prepareCall (sql);
 
      // register the output parameters (4)
      callableStmt.registerOutParameter (1, Types.DOUBLE);
 
      // set all parameters 
      callableStmt.setDouble (1, 0.00);
 
      // call the stored procedure
      con.setAutoCommit(false);  // Enable transactions
      try
      {   System.out.println("Calling stored procedure: " + callName );
          callableStmt.execute (); (5)
 
          // Commit the transaction
          con.commit();
      } 
      catch (Exception e)
      {   // Rollback the transaction
          con.rollback();
          throw e; 
      }
 
      // retrieve output parameters
      double medianSalary = callableStmt.getDouble (1);
 
      // display the information returned from the stored procedure
      System.out.println ("\n  Median Salary: " + medianSalary);
 
      callableStmt.close (); (6)
    }
    catch (Exception e)
    {   System.out.println (e);
    }
  }
}

OUT Stored Procedure Description

  1. Declare Signature. The procedure returns one value: a variable of type DOUBLE. Note that you must specify the OUT host variable as an input parameter in the stored procedure signature.

  2. Turn Off AutoCommit. To ensure that the stored procedure Connection does not automatically issue any COMMIT statements, set the AutoCommit value of the Connection instance to false.

  3. Declare an Iterator Ordered by Salary. The stored procedure declares an Iterator with the ORDER BY SALARY clause.

  4. Determine Total Number of Employees. The stored procedure uses a simple SELECT statement with the COUNT function to retrieve the number of employees in the EMPLOYEE table.

  5. FETCH Median Salary. The stored procedure issues successive FETCH statements until it assigns the median salary to a variable.

  6. Return Median Salary. The stored procedure returns the value of the median salary to the client application.

  7. Return to the Client Application. Java stored procedures do not return values to the client. If the stored procedure is not written in Java, it returns the value SQLZ_DISCONNECT_PROC to the client application if completes successfully, indicating that no further calls to the server procedure will be made.

Example Stored Procedure: Outsrv.sqlj

import java.sql.*;              // JDBC classes
import COM.ibm.db2.app.*;       // StoredProc and associated classes
import sqlj.runtime.*;
import sqlj.runtime.ref.*;
 
#sql iterator Outsrv_Cursor1 (double salary) ;
 
class Outsrv extends StoredProc
{   // (1) stored procedure body 
    public void outputStoredProcedure (          (1)
                                   double medianSalary) throws Exception
    {   try
        {   // Get the DefaultContext
            DefaultContext ctx = DefaultContext.getDefaultContext();
            
            // If the default context is null, set a new one
            if(ctx == null)
            {   // get caller's connection to the database;
                // inherited from StoredProc
                Connection con = getConnection ();
                ctx = new DefaultContext(con);
                DefaultContext.setDefaultContext(ctx);
                con.setAutoCommit(false);        (2)
            }
 
            // Declare Variables
            Outsrv_Cursor1  cursor1;
            short           numRecords;
            int             counter = 0;
            double          sal = 0.00;
  
            // Prepare a Statement to Obtain and Order all Salaries
            #sql cursor1 = { SELECT salary FROM STAFF ORDER BY salary }; (3)
            // Determine the Total Number of Records
            #sql { SELECT COUNT(*) INTO :numRecords FROM STAFF };   (4)
            // Fetch Salaries until the Median Salary is Obtained
            while (counter < numRecords/2 + 1)                      (5)
            {   cursor1.next();
                counter++;
            }
            sal = cursor1.salary(); 
            cursor1.close();
 
            // set value for the output parameter                   (6)
            set (1, sal);
        }
        catch (Exception e)
        {   throw e; 
        }
    }
}

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.

  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.

Note: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 Universal Database for OS/390 or DB2 Universal Database 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.)

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( short *parm1, char *parm2) 

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 decorations for the function name when you call the stored procedure.

Graphic Host Variable Considerations

Any stored procedure written in C or C++, that receives or returns graphic data through its parameter input or output should generally be precompiled with the WCHARTYPE NOCONVERT option. This is because graphic data passed through these parameters 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 parameters 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, see Japanese and Traditional Chinese EUC and UCS-2 Code Set Considerations, and more specifically to Considerations for Stored Procedures.

Multisite Update Consideration

Stored procedures that applications call with CONNECT TYPE 2 cannot issue a COMMIT or ROLLBACK, either dynamically or statically.


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

[ DB2 List of Books | Search the DB2 Books ]