PL/sql简单Pro*C_Makefile

时间:2022-01-08 12:41:59

pcmain.pc

/********************
首先更改Makefile里面对应的环境配置#include 和PROCFLAGS中的include 
Makefile和ph.h中更改:用户名、密码、数据库名
数据库中创建一个表CREATE TABLE xjytab(col1 number,col2 varchar2(20),col3time date,d date);
Compile: make
run:./XJYEASY
根据要求输入1继续其他退出;
如果继续输入:
数值
20个以内的字符串包括空格
年月日
年月日
*******************/

#include<stdio.h>
char g_dbconStop=1;
extern int mainPc();
int main()
{
	int i=0;
    while(i++<10)
    {
		printf("print 1 contintue ,others quit\n");
        scanf("%c",&g_dbconStop);
		getchar();
        if('1'==g_dbconStop)
            mainPc();
           else break;

    }
    printf("successful\n");
return 0;
}
mypc.pc

#include"ph.h"
int getConnection(void *ctx,const char *username,const char*password,const char*dbname)
{
  #undef SQLCA
  EXEC SQL INCLUDE SQLCA;
  EXEC SQL BEGIN DECLARE SECTION;
    VARCHAR USER[21];
    VARCHAR PSW[21];
    VARCHAR DB[21];
  EXEC SQL END DECLARE SECTION;

   char szSQLErr[SQLERRMSG_LEN + 1];
   int nSQLErrNo = E_SQL_SUCCEED;        /*定义全局数据库错误码*/
   sql_context actx=ctx;
   struct timespec waitTime;
   
   USER.len=strlen(username);
   memcpy(USER.arr,username,USER.len);
   PSW.len=strlen(username);
   memcpy(PSW.arr,password,PSW.len);
   DB.len=strlen(dbname);
   memcpy(DB.arr,dbname,DB.len);
AGAIN:
   EXEC SQL CONTEXT USE    :actx;
   EXEC SQL WHENEVER SQLERROR GOTO ERRMETHOD;

   EXEC SQL CONNECT    :USER 
      IDENTIFIED BY    :PSW
      USING            :DB;

   return 1;
ERRMETHOD: 
   GETSQLERROR(szSQLErr,nSQLErrNo);
   if(!g_dbconStop)
   {
     waitTime.tv_sec=5;
     waitTime.tv_nsec=0;
     nanosleep(&waitTime,NULL);
     goto AGAIN;
   }
return 0;
}

int inserttb(void*ctx)
{
  #undef SQLCA
  EXEC SQL INCLUDE SQLCA;
  EXEC SQL BEGIN DECLARE SECTION;
    int C1;
    VARCHAR C2[21];
    VARCHAR C3[9];
    VARCHAR C4[9];
  EXEC SQL END DECLARE SECTION;
  char szSQLErr[SQLERRMSG_LEN + 1];
   int nSQLErrNo = E_SQL_SUCCEED;        /*定义全局数据库错误码*/
   sql_context actx=ctx;
   struct timespec waitTime;
  //********************************************
  //要插入的数据键盘输入,没有进行数据校验
  printf("int , char[20],yyyymmdd,yyyymmdd\n");
  scanf("%d",&C1);//only num
  getchar();//get wrap
  fgets(C2.arr,21,stdin);//string and  wrap and '\0';
  scanf("%s%s",C3.arr,C4.arr);//blank or wrap in string ang string end 
  C2.len=strlen(C2.arr)-1;
  C3.len=strlen(C3.arr);
  C4.len=strlen(C4.arr);
  C2.arr[C2.len]='\0';
  printf("input just now:%d %s %s %s \n",C1,C2.arr,C3.arr,C4.arr);
  //*********************************************

   
  
AGAIN:
   EXEC SQL CONTEXT USE    :actx;
   EXEC SQL WHENEVER SQLERROR GOTO ERRMETHOD;

   EXEC SQL INSERT INTO XJYTAB(COL1,COL2,COL3TIME,D) VALUES(:C1,:C2,to_date(:C3,'yyyymmdd'),to_date(:C4,'yyyymmdd'));
   EXEC SQL COMMIT WORK;
       
   return 1;
ERRMETHOD:
   EXEC SQL WHENEVER SQLERROR continue;
   GETSQLERROR(szSQLErr,nSQLErrNo);
   if(!g_dbconStop&&E_SQL_SUCCEED==nSQLErrNo)
   {
     EXEC SQL ROLLBACK WORK RELEASE;
     getConnection(ctx,sn,sp,sdb);
     goto AGAIN;
   }
return 0;

}
int selecttb(void*ctx)
{
  #undef SQLCA
  EXEC SQL INCLUDE SQLCA;
  EXEC SQL BEGIN DECLARE SECTION;
    int C1;
    VARCHAR C2[21];
    VARCHAR C3[9];
    VARCHAR C4[9];
  EXEC SQL END DECLARE SECTION;
  char szSQLErr[SQLERRMSG_LEN + 1];
   int nSQLErrNo = E_SQL_SUCCEED;        /*定义全局数据库错误码*/
   sql_context actx=ctx;
   struct timespec waitTime;
AGAIN:
   EXEC SQL CONTEXT USE    :actx;
   EXEC SQL WHENEVER SQLERROR GOTO ERRMETHOD;

   EXEC SQL DECLARE MYCursor CURSOR FOR
          select  COL1,COL2,to_char(COL3TIME,'yyyymmdd'),to_char(d,'yyyymmdd')   
          FROM XJYTAB;
   EXEC SQL OPEN MYCursor; 
   EXEC SQL WHENEVER NOT FOUND DO break;
   for(;;)
   {
      EXEC SQL FETCH MYCursor   INTO :C1,:C2,:C3,:C4 ;
      //*******************************************************
      //select 表格,结束符'\0'要自己截断,否则尾部保留上次读取的
      C2.arr[C2.len]='\0';
      C3.arr[C3.len]='\0';
      C4.arr[C4.len]='\0';
      printf("%d %s %s %s\n",C1,C2.arr,C3.arr,C4.arr); 
      //******************************************************* 
   }
   EXEC SQL CLOSE MYCursor;
   EXEC SQL COMMIT WORK;/*会提交事务/释放所有的锁定及其资源*/
   return 1;
ERRMETHOD:
   EXEC SQL WHENEVER SQLERROR continue;//少了这一句会error 标识RRMETHOD 未定义
   GETSQLERROR(szSQLErr,nSQLErrNo);
   if(!g_dbconStop&&E_SQL_SUCCEED==nSQLErrNo)
   {
     EXEC SQL ROLLBACK WORK RELEASE;
     getConnection(ctx,sn,sp,sdb);
     goto AGAIN;
   }
return 0;

}
int mainPc()
{  
    sql_context ctx;
    /*下面不可以有分号‘;’*/
    #undef SQLCA
    EXEC SQL INCLUDE SQLCA;
    EXEC SQL CONTEXT ALLOCATE :ctx;
    EXEC SQL CONTEXT USE      :ctx;
    if(0==getConnection(ctx,sn,sp,sdb))
       return 0;
    inserttb(ctx);
    selecttb(ctx); 
    EXEC SQL COMMIT RELEASE;/*提交事务/释放所有的锁定及其资源/断开与数据库的连接*/
    EXEC SQL CONTEXT FREE :ctx; 
    return 1;
}
ph.h

#ifndef __PH_H
#define __PH_H

#include<stdio.h>
#include<string.h>
#include<time.h>
#include <stdlib.h>  
#define  sn                   "用户名"
#define  sp                   "密码"
#define  sdb                  "数据库名"
#define  SQLERRMSG_LEN        50        /*数据库错误信息最大长度*/
#define	 E_SQL_SUCCEED        0         /*数据库执行成功*/
#define	 E_SQL_KEY_DUPLICATE  1         /*重复键值错误*/
#define  E_SQL_NOT_CONNECTED  2         /*数据库未连接*/
#define  E_SQL_BUSY           3         /*数据库忙*/
#define  E_SQL_OTHER          4         /*其他错误*/


 
/*根据sqlca.sqlcode获取错误类型及错误信息*/
#define GETSQLERROR(pszErrMsg, nSQLErrNo)                           \
{                                       							\
	 printf("%s%d%d",__FILE__,sqlca.sqlcode,__LINE__);             \
     printf("%s%s%d",__FILE__,sqlca.sqlerrm.sqlerrmc,__LINE__);                          \
	if ( -1 == sqlca.sqlcode )                                      \
	{																\
		nSQLErrNo = E_SQL_KEY_DUPLICATE;                          	\
		if(pszErrMsg)												\
			strcpy(pszErrMsg, "重复键值错误");						\
	}																\
	else if (((sqlca.sqlcode == -1012)||(sqlca.sqlcode == -1041)	\
	||(sqlca.sqlcode == -3114)||(sqlca.sqlcode == -3113)			\
	||(sqlca.sqlcode == -1003))										\
	||((sqlca.sqlcode <= -12150)&& (sqlca.sqlcode >= -12285))		\
	||((sqlca.sqlcode >= -12699)&&(sqlca.sqlcode <= -12500)))		\
	{																\
		nSQLErrNo = E_SQL_NOT_CONNECTED;							\
		if(pszErrMsg)												\
			strcpy(pszErrMsg, "数据库未连接");						\
	}																\
	else if (sqlca.sqlcode==-54)									\
	{																\
		nSQLErrNo = E_SQL_BUSY;										\
		if(pszErrMsg)												\
			strcpy(pszErrMsg, "数据库忙");							\
	}																\
	else															\
	{																\
		nSQLErrNo = E_SQL_OTHER;									\
		if(pszErrMsg)												\
			strcpy(pszErrMsg, "其他错误");							\
	}																\
    printf("%s%s%d",__FILE__,pszErrMsg,__LINE__);                   \
}
 
extern char g_dbconStop;
 

#endif

Makefile

#include ${ORACLE_HOME}/precomp/lib/env_precomp.mk
LIBPATH=-L$(ORACLE_HOME)/lib
TARGET=XJYEASY
OJBCTS:=pcmain.o mypc.o
INCLUDES =  -I.
CC=gcc
CFLAGS=
PROC=proc
SYSLIBS= -lclntsh
PROCFLAGS=  sqlcheck=semantic userid=用户名/密码@数据库名  \
           include={$(ORACLE_HOME)/precomp/public,/usr/include,/usr/lib/gcc/x86_64-redhat-linux/4.1.2/include}  \
		   $(INCLUDES)  \
		   code=ANSI_C  parse=FULL \
		   iname=$^  
.SUFFIXES:
.SUFFIXES:.o .c .pc
$(TARGET):$(OJBCTS)
	$(CC)   $^ $(SYSLIBS) $(LIBPATH) $(INCLUDES) -o $@
	@echo "$(TARGET) make successfull"
.c.o:
	$(CC) $(CFLAGS) -c  $< $(INCLUDES)
.pc.c:
	$(PROC) $(PROCFLAGS) 
	@echo 'get mypc.c success'  
clean:
	rm *.o