vs2019 下oracle proc配置


前言

pro*c/c++ 程序 从源码demo.pc 到可执行程序需要经过两次编译。第一次oracle 公司提供的proc编译 把demo.pc编译成 demo.c 或者demo.cpp ,第二次由vs中gcc编译器把demo.c编译链接成demo.exe执行文件 。所以需要在vs中集成proc编译相关配置,而第一次编译时,proc编译器要进行c/c++相关的语法 词法分析 ,也就需要告诉proc按哪个版本的vs相关的头文件进行生成demo.c文件,以便vs进行第二次编译

一、proc集成到vs2019

需要添加 :.proc.exe, precomp头文件目录和库文件目录 ,oci头文件和库文件目录 及precomp动态库

  • 添加proc.exe 目录
    默认安装Oracle时添加了环境变量,可以不用添加。工程项目右键–>属性–>配置属性–> vc++目录–>常规–>可执行文件目录

在这里插入图片描述

  • 头文件目录
    工程项目右键–>属性–>配置属性–> vc++目录–>常规–>包含目录
    在这里插入图片描述
  • 库目录
    工程项目右键–>属性–>配置属性–> vc++目录–>常规–>库目录
    在这里插入图片描述
  • 链接库
    工程项目右键–>属性–>配置属性–>连接器–>输入–>附加依赖项 添加orasql12.lib ,并把该库拷贝到项目路径下
    在这里插入图片描述

二、proc配置中包含vs2019头文件

更改D:\app\oracle\product\12.2.0\dbhome_1\precomp\admin 下的 pcscfg.cfg配置文件 proc.exe 编译时需要vs相关头文件
在这里插入图片描述

三、设置demo.pc 属性

-. c文件

右键demo.pc 文件–>属性–>常规–>项目类型–>自定义生成工具 点击应用
自定义生成工具–>命令行 :proc demo.pc
自定义生成工具–>输出 :demo.c
在这里插入图片描述

  • .c++文件
    右键demo.pc 文件–>属性–>常规–>项目类型–>自定义生成工具 点击应用
    自定义生成工具–>命令行 :proc demo.pc parse=none code=cpp oname=demo.cpp
    自定义生成工具–>输出 :demo.cpp
    在这里插入图片描述
    编译会报error C3861: “gets”: 找不到标识符
    解决办法:把“gets”改成“gets_s”

四、源码

#define _CRT_SECURE_NO_WARNINGS
/* 包含C头文件 */  
#include <stdio.h>  
#include <string.h>  
#include <stdlib.h>  
#include <setjmp.h>  
#include <sqlcpr.h>  
  
/* 包含SQLDA和SQLCA结构 */  
#include <sqlda.h>  
#include <sqlca.h>  
  
/* 定义绑定变量和选择列表项的最大个数 */  
#define MAX_ITEMS       40  
  
/* 定义绑定变量和选择列表项名称的最大长度 */  
#define MAX_VNAME_LEN   30  
  
/* 定义指示变量名称的最大长度 */  
#define MAX_INAME_LEN   30  
  
void connect(); 
void connect2();
void sql_error();  
void alloc_descriptors(int , int , int);  
void dealloc_descriptors();  
void set_bind_variables();  
void process_select_list();  
  
/* 定义绑定描述区和选择描述区 */   
SQLDA* bind_dp;  
SQLDA* select_dp;  
  
/* 定义输入宿主变量:存放动态SQL语句 */  
EXEC SQL BEGIN DECLARE SECTION;
	char sql_stat[100];   
char current_date[20];
EXEC SQL END DECLARE SECTION;
     
  
int main()  
{  
    /* 安装错误处理句柄 */  
    exec sql whenever sqlerror do sql_error();  
  
    /* 连接到数据库 */  
    connect2();  
  
    /* 分配绑定描述区和选择描述区 */  
    alloc_descriptors(MAX_ITEMS , MAX_VNAME_LEN , MAX_INAME_LEN);  
  
    for( ; ; )  
    {  
        printf("开始 please entry sql statements and 'exit' finish:\n");  
        gets(sql_stat);  
  
        /* EXIT(exit):退出 */  
        if(0 == strncmp(sql_stat , "exit" , 4) || 0 == strncmp(sql_stat , "EXIT" , 4))  
            break;  
  
        /* 准备动态SQL语句 */  
        exec sql prepare s from :sql_stat;  
  
        /* 定义游标 */  
        exec sql declare c cursor for s;  
  
        /* 出错,继续下一循环 */  
        if(0 != sqlca.sqlcode)  
            continue;  
  
        /* 设置绑定变量 */  
        set_bind_variables();  
  
        /* 
         * 打开游标 
         * select语句:生成结果集 
         * 其他SQL语句:执行语句 
         */  
        exec sql open c using descriptor bind_dp;  
  
        /* 
         * select语句 
         */  
        if(0 == strncmp(sql_stat , "select" , 6) || 0 == strncmp(sql_stat , "SELECT" , 6)) 
		{  
            process_select_list();   
        }  
        /* 关闭游标 */  
        exec sql close c;  
    }  
  
    /* 释放选择描述区和选择描述区 */  
    dealloc_descriptors();  
  
    /* 提交事务,断开连接 */  
    exec sql commit work release;  
    puts("谢谢使用Oracle动态SQL方法四!\n");  
  
    return 0;  
}  

 
void connect2()  
{  
    /* 定义宿主变量 */ 
	EXEC SQL BEGIN DECLARE SECTION;
	char username[20] , password[20] , server[20]; 
	EXEC SQL END DECLARE SECTION;	
     
  
    /* 输入用户名、口令和网络服务名 */  
    printf("username:");  
    gets(username);  
  
    printf("password: ");  
    gets(password);  
  
    printf("server:");  
    gets(server);  
  
    /* 连接到数据库 */  
    EXEC SQL CONNECT :username identified by :password using :server;  
}  


void sql_error()  
{  
    /* 显示SQL错误信息 */  
    printf("%.*s\n" , sqlca.sqlerrm.sqlerrml , sqlca.sqlerrm.sqlerrmc);  
}  

//struct SQLDA {
  // ub4    // int        N; // Descriptor size in number of entries        //
  // text** // char     **V; // Ptr to Arr of addresses of main variables   //
  // ub4*   // int       *L; // Ptr to Arr of lengths of buffers            //
  // sb2*   // short     *T; // Ptr to Arr of types of buffers              //
  // sb2**  // short    **I; // Ptr to Arr of addresses of indicator vars   //
  // sb4    // int        F; // Number of variables found by DESCRIBE       //
  // text** // char     **S; // Ptr to Arr of variable name pointers        //
  // ub2*   // short     *M; // Ptr to Arr of max lengths of var. names     //
  // ub2*   // short     *C; // Ptr to Arr of current lengths of var. names //
  // text** // char     **X; // Ptr to Arr of ind. var. name pointers       //
  // ub2*   // short     *Y; // Ptr to Arr of max lengths of ind. var. names//
  // ub2*   // short     *Z; // Ptr to Arr of cur lengths of ind. var. names//
 // };
  
void alloc_descriptors(int size , int max_vname_len , int max_iname_len)  
{  
      
    int i;  
  
    /* 分配绑定描述区和选择描述区 */  
    bind_dp = SQLSQLDAAlloc(0 , size , MAX_VNAME_LEN , MAX_INAME_LEN);  
    select_dp = SQLSQLDAAlloc(0 , size , MAX_VNAME_LEN , MAX_INAME_LEN);  
  
  
    /* 为指示变量、绑定变量和选择列表项分配内存 */  
    for(i = 0 ; i != MAX_ITEMS ; ++i)  
    {  
        bind_dp->I[i] = (short*)malloc(sizeof(short));  
        select_dp->I[i] = (short*)malloc(sizeof(short));  
  
        bind_dp->V[i] = (char*)malloc(1);  
        select_dp->V[i] = (char*)malloc(1);  
    }  
}  
  
void dealloc_descriptors()  
{  
    int i;  
  
    /* 释放指示变量、绑定变量和选择列表项占用的内存 */  
    for(i = 0 ; i != MAX_ITEMS ; ++i)  
    {  
        if(bind_dp->V[i] != (char*)0)  
            free(bind_dp->V[i]);  
        free(bind_dp->I[i]);  
  
        if(select_dp->V[i] != (char*)0)  
            free(select_dp->V[i]);  
        free(select_dp->I[i]);  
    }  
  
    /* 释放绑定描述区和选择描述区 */  
    SQLSQLDAFree(0 , bind_dp);  
    SQLSQLDAFree(0 , select_dp);  
}  
  
void set_bind_variables()  
{  
    int i;  
    char bind_var[64];  
  
    /* 设置绑定变量最大个数 */  
    bind_dp->N = MAX_ITEMS;  
  
    /* 绑定变量名称: 绑定描述区 */  
    exec sql describe bind variables for s into bind_dp;  
  
    /* 设置绑定变量实际个数 */  
    bind_dp->N = bind_dp->F;  
  
    /* 循环处理绑定变量 */  
    for(i = 0 ; i != bind_dp->F ; ++i)  
    {  
        /* 显示绑定变量名 */  
        printf("请输入绑定变量%.*s的值:" , (int)bind_dp->C[i] , bind_dp->S[i]);  
  
        /* 输入绑定变量的值 */  
        gets(bind_var);  
  
        /* 设置绑定变量的长度成员 */  
        bind_dp->L[i] = strlen(bind_var);  
  
        /* 为绑定变量数据缓冲区重新分配内存(多一位,留给'\0') */  
        bind_dp->V[i] = (char*)realloc(bind_dp->V[i] , bind_dp->L[i] + 1);  
  
        /* 绑定变量数据: 数据缓冲区 */  
        strcpy(bind_dp->V[i] , bind_var);  
  
        /* 设置指示变量,处理NULL */  
        if(0 == strncmp(bind_var , "NULL" , 4) || 0 == strncmp(bind_var , "null" , 4))  
            *bind_dp->I[i] = -1;  
        else  
            *bind_dp->I[i] = 0;  
  
        /* 设置数据缓冲区数据类型代码->char */  
        bind_dp->T[i] = 1;  
    }  
}  
  
void process_select_list()  
{  
    int i , null_ok , precision , scale;  
    char title[MAX_VNAME_LEN];  
  
    /* 设置选择列表项的最大个数 */  
    select_dp->N = MAX_ITEMS;  
  
    /* 选择列表项: 选择描述区 */  
    exec sql describe select list for s into select_dp;  
  
    /* 设置选择列表项的实际个数 */  
    select_dp->N = select_dp->F;  
  
    /* 循环处理选择列表项 */  
    for(i = 0 ; i != select_dp->F ; ++i)  
    {  
        /* 清除select_dp->T[i]的高位->null */  
        SQLColumnNullCheck(0 , (unsigned short*)&select_dp->T[i]  
            , (unsigned short*)&select_dp->T[i] , &null_ok);  
  
        /* 根据内部数据类型确定外部类型数据长度(显示长度) */  
        switch(select_dp->T[i])  
        {  
        case 2:  
            /* number类型,取得精度与标度 */  
            //SQLNumberPrecV6(0 , (unsigned short*)&select_dp->T[i] , &precision , &scale); 
            SQLNumberPrecV6(0 , (unsigned int *)&select_dp->L[i] , &precision , &scale);  //wangbaoming modify 201409
			
            if(scale > 0)  
                /* 实数: 显示长度:float  */  
                select_dp->L[i] = sizeof(float);  
            else  
                /* 整数: 显示长度 int */  
                select_dp->L[i] = sizeof(int);  
            break;  
        case 12:  
            /* DATA数据类型(DD-MON-YY) */  
            select_dp->L[i] = 9;  
            break;  
        }  
  
        /* 根据变量长度,重新为选择列表项数据缓冲区分配内存 */  
        if(2 != select_dp->T[i])  
            /* 其他类型 */  
            select_dp->V[i] = (char*)realloc(select_dp->V[i] , select_dp->L[i] + 1);  
        else  
            /* number类型 */  
            select_dp->V[i] = (char*)realloc(select_dp->V[i] , select_dp->L[i]);  
  
        /* 初始化title */  
        memset(title , ' ' , MAX_VNAME_LEN);  
  
        /* 选择列表项名称: title */  
        strncpy(title , select_dp->S[i] , select_dp->C[i]);  
  
        /* 显示列名 */  
        if(2 == select_dp->T[i])  
            if(scale > 0)  
                printf("\t%.*s" , select_dp->L[i] + 3, title);  
            else  
                printf("\t%.*s" , select_dp->L[i] , title);  
        else  
            printf("\t%-.*s" , select_dp->L[i] , title);  
  
        /* 根据Oracle内部类型确定外部数据类型(显示类型) */  
        if( 2 == select_dp->T[i])  
        {  
            /* number 类型*/  
            if(scale > 0)  
                /* float */  
                select_dp->T[i] = 4;  
            else  
                /* int */  
                select_dp->T[i] = 3;  
        }  
        else  
            /* char */  
            select_dp->T[i] = 1;  
    }  
  
    printf("\n");  
  
    /* 提取数据完毕->结束循环 */  
    exec sql whenever not found do break;  
  
    /* 循环处理选择列表数据 */  
    for( ; ; )  
    {  
        /* 数据->选择描述区 */  
        exec sql fetch c using descriptor select_dp;  
  
        /* 显示数据 */  
        for( i = 0 ; i != select_dp->F ; ++i)  
        {  
            if(*select_dp->I[i] < 0){  
                /* 处理NULL */  
                printf("\tNULL");  
            }else{  
                if(3 == select_dp->T[i]) {  
                    /* int */  
                    printf("\t%d" , *(int*)select_dp->V[i]);  
                }else if(4 == select_dp->T[i]){  
                    /* float */  
                    printf("\t%8.2f" , *(float*)select_dp->V[i]);  
                }else{  
                    /* char */  
                    printf("\t%.*s" , select_dp->L[i] , select_dp->V[i]);  
                }  
                }  
        }  
        printf("\n");  
    }  
}  


  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值