当前位置: 首页 > 工具软件 > Pro*C > 使用案例 >

Pro*C 程序编程(一)

陶星辰
2023-12-01
Pro*C编写程序与在PB中直接用SQL语句类似,在PB中能用的SQL语法在Pro C中同样适用,数据库能用的函数也都可以使用,所有的SQL语句都应符合Oracle的语法,只是多一些C语言中的语法和限制,下面是一个最简单的例子:
 
/*****************************************************************/
/*程序开始,有一些需要包含的.H文件*/
#include <stdio.h>
#ifdef _WIN32
        #define DLLIMPORT __declspec(dllimport)
        #define DLLEXPORT __declspec(dllexport)
        #define CDECL __cdecl
#else
        #define DLLIMPORT
        #define DLLEXPORT
        #define CDECL
#endif
#define SQLCA_STORAGE_CLASS extern
/*SQL没有记录的返回值*/
#define SQLNOTFOUND 1403
/*Pro C必须在每一个程序中写的语句,SQLCA的大小写必须所有程序一致*/
EXEC SQL INCLUDE SQLCA;
EXEC ORACLE OPTION (RELEASE_CURSOR = YES); /*该语句可以在Makefile中写*/
/*有了下面的定义,就不需要进行变量类型的等价了VAR IS STRING()*/
EXEC ORACLE OPTION (CHAR_MAP = STRING); /*该语句可以在Makefile中写*/
void main()
{
  /*声明需要在SQL语句中使用的变量,这些变量在非SQL中也能使用*/
  EXEC SQL BEGIN DECLARE SECTION;
        char szCodeName[41] = ""; /*CHAR变量的长度必须比数据库中大1*/
  /*对VARCHAR类型必须进行等价说明,否则可能有空格,或设置CHAR_MAP=STRING*/
        EXEC SQL VAR szCodeName IS STRING(41);
  /*指示变量,必须是short int 类型,*/
  short int indCodeName = 0; 
  /*与EXEC SQL BEGIN DECLARE SECTION;成对使用*/
  EXEC SQL END DECLARE SECTION;
  /*也可以不需要EXEC SQL BEGIN /END DECLARE SECTION;,在编译上控制*/
  strcpy(szConnectString,"
jifei/jifei@jifei");
  /*连接数据库*/
        EXEC SQL connect :szConnectString;
  /*或EXEC SQL CONNECT :szUser IDENTIFIED BY :szPassword using :szDBString;*/
  if (sqlca.sqlcode !=0) /*判断SQL语句是否执行成功*/
  {
   printf("Connect Error , Error Message : %s/n",sqlca.sqlerrm.sqlerrmc);
   exit(0);
  }
        EXEC SQL select code_name into :szCodeName
          from CODE_NAME where rownum = 1;
  if (sqlca.sqlcode < 0) /*判断SQL语句是否执行成功*/
  {
   printf("Connect Error , Error Message : %s/n",sqlca.sqlerrm.sqlerrmc);
   EXEC SQL rollback work release;
   exit(0);
  }
  if (sqlca.sqlcode == SQLNOTFOUND) /*没有结果,必须用SQLNOTFOUND,不要直接用1403*/
  {
   printf("No Data to Fetch/n");
   EXEC SQL rollback work release;
   exit(0);
  }
        printf("Code_Name = %s./n",szCodeName);
  /*提交并断开连接*/
        EXEC SQL commit work release;
}
/************************************************************/
 
一些基本的用法:

1、VARCHAR2型变量的数据定义

如果数据库中是varchar2型的字段,在Pro*C中类型定义成char szFieldName[n+1]

如果在Makefile文件中的预编译参数中char_map=STRING则不需要进行类型等价,否则需要进行字符类型的等价定义:

EXEC SQL VAR szFieldName IS STRING(n+1);

如不进行等价,则变量用空格填充。

2、判断NULL值的方法

Pro* C中,如某一个字段是NULL值,sqlca.sqlcode是小于0的,所以对可能出现NULL的列在into 语句中用指示变量则sqlca.sqlcode = 0,这时指示变量= -1

EXEC SQL select col1 into :nCol1 :indCol1 ......

if (indCol1 == -1)  /*Col1NULL,必须处理*/

{   nCol1 = 0;

}

注意     :nCol1:indCol1之间没有“,”号

3、错误处理的方法

    在Pro*C中可以对每一条语句判断其sqlca.sqlcode来做错误判断,也可以用类型Oracle的异常处理的方式:

EXEC SQL WHENEVER SQLERROR goto Error_Exit;

Error_Exit:

    EXEC SQL WHENEVER SQLERROR continue;    /*停止错误处理*/

    exec sql rollback;

    gf_PrintMess("提款反销失败:Point = %d",iBKPoint);

       #ifdef _DEBUG_

    gf_PrintMess("SQL = %s",szSQL);

#endif

    gf_PrintMess("=========提款反销====Error");

    cics_return(-1,ERROR_DB,sqlca.sqlcode,sqlca.sqlerrm.sqlerrmc);

    return;

对其他错误也能进行异常处理定义,如 NOT FOUND,不过,一般不这样做。这样所有的SQL语句后会自动判断sqlca.sqlcode是否小于0,如小于0则goto Error_Exit。在C语句中是不建议用goto语句的,所以如果一个程序只有一种错误处理方式,即只要出错就返回这么用也是很方便、很直观的。

4、结构在SQL语句种的使用

对定义的结构,如与查询的结果列一致,可以直接使用,如

select a1,a2 into :str_a1a2……

5、数组在SQL语句中的使用:

   A、FETCH Cursor中的使用

       #define     MAX_ACCT_ROWS   10000   /*定义每次处理的用户数=1*/

            struct _AcctFund{

                 ulong   ulAcctID[MAX_ACCT_ROWS];    /*付费编号*/

                 long    lBalance[MAX_ACCT_ROWS];        /*存款余额*/

                 VARCHAR szRowID[MAX_ACCT_ROWS][20];     /*ACCT_FUND中的ROWID*/

             } astrAcctFund;

            EXEC SQL FOR :MAX_ACCT_ROWS FETCH Cur_fund INTO

                 :astrAcctFund.ulAcctID,

                 :astrAcctFund.lBalance,

                 :astrAcctFund.szRowID[0];

           iRows_fund = sqlca.sqlerrd[2];  /*记录数*/

 

       #define     MAX_ACCT_ROWS   10000   /*定义每次处理的用户数=1*/

            struct _AcctFund{

                 ulong   ulAcctID[MAX_ACCT_ROWS];    /*付费编号*/

                 long    lBalance[MAX_ACCT_ROWS];        /*存款余额*/

                 VARCHAR szRowID[MAX_ACCT_ROWS][20];     /*ACCT_FUND中的ROWID*/

             } astrAcctFund;

            EXEC SQL FOR :MAX_ACCT_ROWS FETCH Cur_fund INTO

                 :astrAcctFund.ulAcctID,

                 :astrAcctFund.lBalance,

                 :astrAcctFund.szRowID[0];

           iRows_fund = sqlca.sqlerrd[2];  /*记录数*/

 

   B、Insert 中使用

            int nID[100] ;

            EXEC SQL FOR 100 insert into t_a values (:nID);

   C、Where 中使用

            int nID[100];

            EXEC SQL for 100 delete from t_a where id = :nID;

   D、动态语句中使用

            int nID[100];

            strcpy(szSql,insert into t_a values(:v1));

            EXEC SQL PREPARE st_EXE_Sql FROM :szSql;

       EXEC SQL FOR 100

                 EXECUTE st_EXE_print using :nID;

 

 

   E、结构数组的使用

        struct _S_TYPE {

            int  nCodeId;

            char szCodeName[41];

        }s_Type[100];

        _S_TYPE *psType = &s_Type[0];   /*必须定义一个指针*/

        EXEC SQL for 100

            select code_id,code_name into :psType

       from CODE_ID_NAME where rownum <= 100;

        这种用法比使用数组结构简单,但要求select的列数与数组结构的列数一致。

        这种用法比使用数组结构简单,但要求select的列数与数组结构的列数一致。

6、Pro C中使用存储过程

    EXEC SQL EXECUTE

        BEGIN

        up_db_pay_open(:iPartID,:aszAcctID,0,1,:aszOperSerialNbr,

            :aszStaffID,2,:iPartOpen,:aszOweState,

            :iErrPB,:lErrSys,:szErrSysMsg);

        END;

    END-EXEC;

 7、Pro C程序的编译

 7、Pro C程序的编译

#####################################

proc.mkPro C程序的编译 Makefile,makefile

make

test1.mk

make f test1.mk [test1]

#####################################

#ORACLE_HOME = /oracle/app/oracle/product/8.0.6

PROC_PL = $(ORACLE_HOME)/bin/proc parse=FULL release_cursor=no USERID=bill/AC6C69626 sqlcheck=SEMANTICS char_map=STRING ireclen=512 iname=

#如果在Pro*C中没有使用存储过程,SQLCHECK可以等于syntax

CCFLAGS = -L$(ORACLE_HOME)/lib   -lclntsh -lm -lld -D_DEBUG_

COMPILE = xlc_r4 -c $(CICSFLAGS) $(CCFLAGS)   -o

 

.SUFFIXES:  .pc .c .o

.pc.c:

    $(PROC_PL) $<

.c.o:

    $(CC) $(CCFLAGS) -c $<

.pc.o:

    $(PROC_PL) $<

    $(CC) $(CFLAGS) -c $(<:.pc=.c)

test : test.o fbillpub.o

    $(COMPILE) test.o o test

 

 

 类似资料: