ivhb 发表于 2007-07-07 18:41

发发牢骚,被ODBC接口折磨死了....

要得到procedure的返回值,oracle下和informix还不一样,直到看到informix下关于procudure调用的DEMO才知,原来需要BindCol才可以得到他的返回。
BindParameter,都bind无数次了,执行总说不对。不知道什么地方搞错了一些,
唉,要疯了.....

大梦 发表于 2007-07-11 20:07

/***************************************************************************
*        Licensed Materials - Property of IBM
*
*
*        "Restricted Materials of IBM"
*
*
*
*        IBM Informix Client SDK
*
*
*        (C) Copyright IBM Corporation 1997, 2004 All rights reserved.
*
*
*
*
*
*Title:          proc.c
*
*Description:    To execute a stored procedure returning multiple results
*
*                  The stored procedure executed is -
*                         PROCEDURE multiReturnProc (i integer)
*                      RETURNING integer;
*                        define j integer;
*                        for j in (1 to 5)
*                            return i*j with resume;
*                        end for;
*                  END PROCEDURE
*
*                  Because the Informix ODBC driver version 3.3 does not
*                  yet suport output parameters for stored procedures,
*                  the way to get return values from a procedure is to
*                  use SQLBindCol and SQLFetch. This works whether the
*                  procedure returns a single value or multiple values.
*
*
***************************************************************************
*/


#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#ifndef NO_WIN32
#include <io.h>
#include <windows.h>
#include <conio.h>
#endif /*NO_WIN32*/

#include "infxcli.h"


#define ERRMSG_LEN      200

SQLCHAR   defDsn[] = "odbc_demo";


SQLINTEGER checkError (SQLRETURN       rc,
                SQLSMALLINT   handleType,
                                SQLHANDLE       handle,
                                SQLCHAR*            errmsg)
{
    SQLRETURN       retcode = SQL_SUCCESS;

    SQLSMALLINT   errNum = 1;
        SQLCHAR                  sqlState;
    SQLINTEGER      nativeError;
        SQLCHAR                  errMsg;
    SQLSMALLINT   textLengthPtr;


    if ((rc != SQL_SUCCESS) && (rc != SQL_SUCCESS_WITH_INFO))
    {
      while (retcode != SQL_NO_DATA)
      {
            retcode = SQLGetDiagRec (handleType, handle, errNum, sqlState, &nativeError, errMsg, ERRMSG_LEN, &textLengthPtr);

            if (retcode == SQL_INVALID_HANDLE)
            {
                fprintf (stderr, "checkError function was called with an invalid handle!!\n");
                return 1;
            }

            if ((retcode == SQL_SUCCESS) || (retcode == SQL_SUCCESS_WITH_INFO))
                fprintf (stderr, "ERROR: %d:%s : %s \n", nativeError, sqlState, errMsg);

            errNum++;
      }

      fprintf (stderr, "%s\n", errmsg);
      return 1;   /* all errors on this handle have been reported */
    }
        else
                return 0;        /* no errors to report */
}




int main (long         argc,
          char*      argv[])
{
        /* Declare variables
    */

    /* Handles */            
        SQLHDBC   hdbc;
    SQLHENV   henv;
    SQLHSTMT    hstmt;

    /* Miscellaneous variables */

    SQLCHAR       dsn;   /*name of the DSN used for connecting to the database*/
    SQLRETURN   rc = 0;
        SQLINTEGER         in;


    SQLCHAR*       createProcStmt = (SQLCHAR *) "CREATE PROCEDURE multiReturnProc (i integer)\
                                  RETURNING integer;\
                                    define j integer;\
                                    for j in (1 to 5)\
                                        return i*j with resume;\
                                    end for;\
                                  END PROCEDURE;";

    SQLCHAR*       dropProcStmt = (SQLCHAR *) "DROP PROCEDURE multiReturnProc";
    SQLSMALLINT       inputParam = 2;
    SQLINTEGER         retVal = 7, cbRetVal = 0, cbInputParam = 0;
   
   
    /*STEP 1. Get data source name from command line (or use default)
    **          Allocate the environment handle and set ODBC version
    **          Allocate the connection handle
    **          Establish the database connection
    **          Allocate the statement handle
    */


    /* If(dsn is not explicitly passed in as arg) */
    if (argc != 2)
    {
      /* Use default dsn - odbc_demo */
      fprintf (stdout, "\nUsing default DSN : %s\n", defDsn);
      strcpy ((char *)dsn, (char *)defDsn);
    }
    else
    {
      /* Use specified dsn */
      strcpy ((char *)dsn, (char *)argv);
      fprintf (stdout, "\nUsing specified DSN : %s\n", dsn);
    }

   
    /* Allocate the Environment handle */
    rc = SQLAllocHandle (SQL_HANDLE_ENV, SQL_NULL_HANDLE, &henv);
    if (rc != SQL_SUCCESS)
    {
      fprintf (stdout, "Environment Handle Allocation failed\nExiting!!");
      return (1);
    }


    /* Set the ODBC version to 3.0 */
    rc = SQLSetEnvAttr (henv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER) SQL_OV_ODBC3, 0);
    if (checkError (rc, SQL_HANDLE_ENV, henv, (SQLCHAR *) "Error in Step 1 -- SQLSetEnvAttr failed\nExiting!!"))
                return (1);


    /* Allocate the connection handle */
    rc = SQLAllocHandle (SQL_HANDLE_DBC, henv, &hdbc);
    if (checkError (rc, SQL_HANDLE_ENV, henv, (SQLCHAR *) "Error in Step 1 -- Connection Handle Allocation failed\nExiting!!"))
                return (1);


    /* Establish the database connection */
    rc = SQLConnect (hdbc, dsn, SQL_NTS, (SQLCHAR *) "", SQL_NTS, (SQLCHAR *) "", SQL_NTS);
        if (checkError (rc, SQL_HANDLE_DBC, hdbc, (SQLCHAR *) "Error in Step 1 -- SQLConnect failed\nExiting!!"))
                return (1);


    /* Allocate the statement handle */
    rc = SQLAllocHandle (SQL_HANDLE_STMT, hdbc, &hstmt );
    if (checkError (rc, SQL_HANDLE_DBC, hdbc, (SQLCHAR *) "Error in Step 1 -- Statement Handle Allocation failed\nExiting!!"))
                return (1);
   
   

        fprintf (stdout, "STEP 1 done...connected to database\n");




        /* STEP 2.Create the stored procedure in the database
    */

    /* Execute the SQL statement to create the stored procedure*/
    rc = SQLExecDirect (hstmt, createProcStmt, SQL_NTS);
    if (checkError (rc, SQL_HANDLE_STMT, hstmt, (SQLCHAR *) "Error in Step 2 -- SQLExecDirect failed\n"))
                goto Exit;

          
        fprintf (stdout, "STEP 2 done...stored procedure created\nExecuting procedure...\n\n");




    /* STEP 3.Bind the input parameter
    **          Execute the procedure
    **          Bind the result set column (return values)
    **          Fetch the results
    **          Display the results
    **          Close the result set cursor
    */

    /* Bind the input parameter */
    rc = SQLBindParameter (hstmt, 1, SQL_PARAM_INPUT, SQL_C_SSHORT, SQL_INTEGER, 0, 0, &inputParam, 0, &cbInputParam);
    if (checkError (rc, SQL_HANDLE_STMT, hstmt, (SQLCHAR *) "Error in Step 3 -- SQLBindParameter failed\n"))
                return (1);

    /* Execute the procedure */
    rc = SQLExecDirect (hstmt, (SQLCHAR *) "{call multiReturnProc (?)}", SQL_NTS);
    if (checkError (rc, SQL_HANDLE_STMT, hstmt, (SQLCHAR *) "Error in Step 3 -- SQLExecDirect failed\n"))
            goto Exit;

    /* Bind the result set column */
    rc = SQLBindCol (hstmt, 1, SQL_C_SLONG, (SQLPOINTER)&retVal, 0, &cbRetVal);
    if (checkError (rc, SQL_HANDLE_STMT, hstmt, (SQLCHAR *) "Error in Step 3 -- SQLBindCol failed\n"))
                goto Exit;

    /* Fetch and display the results */
    while (1)
    {
          rc = SQLFetch (hstmt);
               if (rc == SQL_NO_DATA_FOUND)
                break;
      else if (checkError (rc, SQL_HANDLE_STMT, hstmt, (SQLCHAR *) "Error in Step 3 -- SQLFetch failed\n"))
                  goto Exit;

      /* Display the results */
      fprintf (stdout, "Procedure returned %d\n", retVal);
    }

    /* Close the result set cursor */
    rc = SQLCloseCursor (hstmt);
    if (checkError (rc, SQL_HANDLE_STMT, hstmt, (SQLCHAR *) "Error in Step 3 -- SQLCloseCursor failed\n"))
                goto Exit;


        fprintf (stdout, "\nSTEP 3 done...stored procedure executed\n");



    Exit:

    /* CLEANUP: Drop the stored procedure from the database
    **          Close the statement handle
    **          Free the statement handle
    **          Disconnect from the datasource
    **          Free the connection and environment handles
    **          Exit
    */

           /* Drop the stored procedure from the database */
    SQLExecDirect (hstmt, dropProcStmt, SQL_NTS);

    /* Close the statement handle */
    SQLFreeStmt (hstmt, SQL_CLOSE);

    /* Free the statement handle */
    SQLFreeHandle (SQL_HANDLE_STMT, hstmt);

        /* Disconnect from the data source */
    SQLDisconnect (hdbc);

    /* Free the environment handle and the database connection handle */
    SQLFreeHandle (SQL_HANDLE_DBC, hdbc);
    SQLFreeHandle (SQL_HANDLE_ENV, henv);

    fprintf (stdout,"\n\nHit <Enter> to terminate the program...\n\n");
    in = getchar ();
    return (rc);
}
页: [1]
查看完整版本: 发发牢骚,被ODBC接口折磨死了....