/**********************************************************************
* FILENAME :    CallSPWithParamArray
*
*
* DESCRIPTION :
*               Simple ODBC example to SELECT data from a table via a
*               stored procedure which takes an array of parameters.
*
*               The stored procedure takes one parameter,
*               in the form :
*
*               {CALL Stored_Procedure (?)}
*
* ODBC USAGE :
*               Creates an array of record ids (PersonID) to select
*               from TestTBL1 via a stored procedure 'Find_Record'
*               Drops and recreates a procedure 'Find_Record'
*               Creates statement handle and sets up parameter array
*               usage with SQLSetStmtAttr() to specify :
*                       SQL_ATTR_PARAMSET_SIZE
*                       SQL_ATTR_PARAM_STATUS_PTR
*                       SQL_ATTR_PARAMS_PROCESSED_PTR
*               Binds the address of first element of the parameter
*               array to parameter 1 of the stored proc.
*               Executes the stored proc using SQLExecDirect() and
*               uses SQLNumResultCols(), SQLFetch(), SQLRowCount() and
*               SQLMoreResults() to process the records set(s) returned.
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <sql.h>
#include <sqlext.h>
#include <string.h>

#include "util.c"
#include "CallSPUtil.c"

#define PARAM_ARRAY_SIZE 50 // number of params in param array

int main () {

    SQLHENV  henv  = SQL_NULL_HENV;   	// Environment
    SQLHDBC  hdbc  = SQL_NULL_HDBC;   	// Connection handle
    SQLHSTMT hstmt = SQL_NULL_HSTMT;  	// Statement handle
    SQLRETURN retcode;			// Return status

    SQLCHAR * strCallSP   = "{CALL Find_Record(?)}";
    char    * strProcName = "Find_Record";
    SQLSMALLINT columns; 		// Number of columns in result-set
    int i, count;

    SQLINTEGER   pPersonIDs [PARAM_ARRAY_SIZE] =
                 {111,2,3,4,5,6,7,8,9,10,
                  11,12,13,14,15,16,17,18,19,20,
                  21,22,23,24,25,26,27,28,29,30,
                  31,32,33,34,35,36,37,38,39,40,
                  41,42,43,44,45,46,47,48,49,50};

    SQLUSMALLINT ParamStatusArray[PARAM_ARRAY_SIZE];
    SQLINTEGER   ParamsProcessed=0;

    // Allocate an environment handle
    retcode=SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &henv);
    CHECK_ERROR(retcode, "SQLAllocHandle(ENV)", henv, SQL_HANDLE_ENV);

    // Set ODBC Version
    retcode=SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION,
                          (void *) SQL_OV_ODBC3, 0);
    CHECK_ERROR(retcode, "SQLSetEnvAttr(SQL_ATTR_ODBC_VERSION)",
                henv, SQL_HANDLE_ENV);

    // Allocate a connection handle
    retcode=SQLAllocHandle(SQL_HANDLE_DBC, henv, &hdbc);
    CHECK_ERROR(retcode, "SQLAllocHandle(SQL_HANDLE_DBC)",
                hdbc, SQL_HANDLE_DBC);

    // DSN
    retcode=SQLDriverConnect(hdbc, NULL, "DSN=DATASOURCE;", SQL_NTS,
                             NULL, 0, NULL, SQL_DRIVER_COMPLETE);
    CHECK_ERROR(retcode, "SQLDriverConnect(DATASOURCE)",
                hdbc, SQL_HANDLE_DBC);

    retcode = DropProcedure (hdbc, strProcName);
    retcode = CreateProcedure (hdbc, strProcName);
    retcode = ListProcedure (hdbc, strProcName);

    // Allocate a statement handle
    retcode=SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt);
    CHECK_ERROR(retcode, "SQLAllocHandle(SQL_HANDLE_STMT)",
                hstmt, SQL_HANDLE_STMT);

    // Setup for parameter array processing
    retcode = SQLSetStmtAttr (hstmt, SQL_ATTR_PARAMSET_SIZE,
                              (SQLPOINTER) PARAM_ARRAY_SIZE, 0);
    retcode = SQLSetStmtAttr (hstmt, SQL_ATTR_PARAM_STATUS_PTR,
                              ParamStatusArray, PARAM_ARRAY_SIZE);
    retcode = SQLSetStmtAttr (hstmt, SQL_ATTR_PARAMS_PROCESSED_PTR,
                              &ParamsProcessed, 0);

    // Bind array values of parameter 1 data in
    retcode = SQLBindParameter(hstmt, 1, SQL_PARAM_INPUT, SQL_C_LONG,
                               SQL_INTEGER, 0, 0, pPersonIDs, 0, NULL);
    CHECK_ERROR(retcode, "SQLBindParameter(SQL_PARAM_INPUT)",
                hstmt, SQL_HANDLE_STMT);

    retcode = SQLExecDirect (hstmt, strCallSP, SQL_NTS);
    CHECK_ERROR(retcode, "SQLExecDirect(SQL_HANDLE_STMT)",
                hstmt, SQL_HANDLE_STMT);

    printf ("\nPersonID   Firstname     Surname    Address       City");
    printf ("\n--------   ---------     -------    -------       ----\n");

    SQLLEN  indicator, RowCount;
    char *buf=malloc (255);
    int params=1;
    do {
        // SQLNumResultCols() returns number of columns in result set.
        // If non zero use SQLFetch until SQL_NO_DATA returned
        retcode=SQLNumResultCols(hstmt, &columns);
       	CHECK_ERROR(retcode, "SQLNumResultCols()", hstmt, SQL_HANDLE_STMT);
        printf ("\nColumns : %i", columns);
        if (columns > 0) {
            printf ("\nParam No : %i", params);
            printf ("\nStart Fetch ...");
            while (SQLFetch(hstmt) != SQL_NO_DATA) {
        	    // Loop through the columns
        		memset (buf, ' ', 255);
                printf ("\n");
        	for (i = 1; i <= columns; i++) {
        	    // retrieve column data as a string
        	    retcode = SQLGetData(hstmt, i, SQL_C_CHAR,
                                         buf, 255, &indicator);
        		if (SQL_SUCCEEDED(retcode)) {
        	            // Handle null columns
        		    if (indicator == SQL_NULL_DATA)
                                strcpy (buf, "NULL");
        		    	buf=rtrim(buf, ' ');
        		        printf("%10s ", buf);
        		}
        	    }
            }
            printf ("\nEnd Fetch ...");
        }
        else {
            // SQLRowCount returns number of rows affected by INSERT, UPDATE,
            // DELETE or (if supported by the driver) number of rows returned
            // by a SELECT
            retcode=SQLRowCount(hstmt, &RowCount);
        	CHECK_ERROR(retcode, "SQLRowCount()", hstmt, SQL_HANDLE_STMT);
            printf ("\nRow count is : %i", (int) RowCount);
            params++;
        }
        if (columns==0)
            printf ("\n-----------");
    } while (SQLMoreResults(hstmt) == SQL_SUCCESS);

exit:

    free (buf);

    printf ("\nComplete.\n");

    // Free handles
    // Statement
    if (hstmt != SQL_NULL_HSTMT)
        SQLFreeHandle(SQL_HANDLE_STMT, hstmt);

    // Connection
    if (hdbc != SQL_NULL_HDBC) {
        SQLDisconnect(hdbc);
        SQLFreeHandle(SQL_HANDLE_DBC, hdbc);
    }

    // Environment
    if (henv != SQL_NULL_HENV)
        SQLFreeHandle(SQL_HANDLE_ENV, henv);

    return 0;
}

See Also


Oracle is a registered trademark of Oracle Corporation and/or its affiliates.