朋友托我写个OCI程序
来源:互联网 发布:知乎 湖南农民考察报告 编辑:程序博客网 时间:2024/05/16 09:07
朋友托我写个OCI程序,于是到网上东拼西凑,搞了个
1. 平台:AIX或LINUX
2. makefile
### makefile : My first OTLV4 For Oracle On AIX 2009-12-1 by tan
PRECOMPHOME=$$ORACLE_HOME/precomp/public
PROCINCLUDE=include=. /
include=${ORACLE_HOME}/precomp/syshdr /
include=${ORACLE_HOME}/precomp/public /
include=${ORACLE_HOME}/rdbms/public /
include=${ORACLE_HOME}/rdbms/demo /
include=${ORACLE_HOME}/plsql/public /
include=${ORACLE_HOME}/network/public /
include=$(ORACLE_HOME)/precomp/lib/env_precomp.mk
ORALIBPATH=$(ORACLE_HOME)/lib
ORALIBS=-locci -lclntsh -ldl -lm -lnsl
INCLUDE= -I. -I/usr/include -I/usr/vacpp/include -I${ORACLE_HOME}/precomp/public /
-I${ORACLE_HOME}/rdbms/public /
-I${ORACLE_HOME}/rdbms/demo /
-I${ORACLE_HOME}/plsql/public
LIBPATH=-L/usr/vacpp/lib -L/lib -L$(ORALIBPATH) $(ORALIBS) #-L/usr/lib
CC = xlC -q64
#CC=g++ -g
CC_FLAGS =
PROGRAM = run
ALL : $(PROGRAM)
.SUFFIXES: .cpp .c .cc .cxx .o
.DEFAULT : all
SRCS = storedproc.cpp myoci.cpp
OBJS = $(SRCS:.cpp=.o)
$(PROGRAM) : $(OBJS)
$(CC) $(INCLUDE) $(LIBPATH) $(OBJS) -o $(PROGRAM) ${LIBPATH}
.cpp.o:
$(CC) $(INCLUDE) $(CC_FLAGS) -c $<
clean:
- rm -f ./*.o ./*.a ./$(PROGRAM)
### END---MAKEFILE
3.
// myoci.h:
#ifndef __MY_OCI_H__
#define __MY_OCI_H__
#include <oci.h>
#define OK 1
#define ERROR 0
/*--- define OCI handle struct---*/
typedef struct{
OCIEnv *p_env;
OCIError *p_err;
OCISvcCtx *p_svc;
OCIStmt *p_sql;
OCIDefine *p_dfn;
OCIBind *p_bnd;
}OCIDATA;
/*--- output error information ---*/
void error_proc(dvoid *errhp, sword status);
/*--- create env and initialize OCI handle ---*/
void ociCreatEvnHandle(OCIDATA *data);
/*--- logon oracle database ---*/
void ociLogon(OCIDATA *data, char *user, char *pwd, char *servername);
/*--- prepare sql ---*/
void ociStmtPrepare(OCIDATA *data, char *strSql);
/*--- bind data on array from database ---*/
void ociDefineByPos(OCIDATA *data, int pos, char *out, ub2 type);
/*--- execute sql ---*/
sword ociStmtExecute(OCIDATA *data);
/*--- fetch data until output finish ---*/
sword ociStmtFetch(OCIDATA *data);
/*--- logoff and release handles ---*/
void ociHandleFree(OCIDATA *data);
int oci_insert(char *sql, char * out);
int oci_query(char *sql, char *out);
void ociCreatEvnHandle(OCIDATA *data);
void ociDefineByPos(OCIDATA *data, int pos, char *out, ub2 type);
void ociHandleFree(OCIDATA *data);
void ociLogon(OCIDATA *data, char *user, char *pwd, char *servername);
sword ociStmtExecute(OCIDATA *data);
sword ociStmtFetch(OCIDATA *data);
void ociHandleFree(OCIDATA *data);
#endif // __MY_OCI_H__
4.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <oci.h>
#include "myoci.h"
CONST char *DB_USER = "CRMCN_DEMO";
CONST char *DB_PASSWORD = "CRMCN_DEMO";
CONST char *DB_DBNAME = "DEVDB150";
static OCIEnv *p_env;
static OCIError *p_err;
static OCISvcCtx *p_svc;
static OCIStmt *p_sql;
static OCIDefine *p_dfn = (OCIDefine *) 0;
static OCIBind *p_bnd = (OCIBind *) 0;
int oci_insert(char *sql, char * out)
{
int p_bvi;
char *p_sli;
char *p_sli1;
int rc;
char errbuf[100];
int errcode;
/* Initialize OCI evironment*/
rc = OCIEnvCreate((OCIEnv **) &p_env,OCI_DEFAULT,(dvoid *)0,
(dvoid * (*)(dvoid *, size_t)) 0,
(dvoid * (*)(dvoid *, dvoid *, size_t))0,
(void (*)(dvoid *, dvoid *)) 0,
(size_t) 0, (dvoid **) 0);
/* Initialize handles */
rc = OCIHandleAlloc( (dvoid *) p_env, (dvoid **) &p_err, OCI_HTYPE_ERROR,
(size_t) 0, (dvoid **) 0);
rc = OCIHandleAlloc( (dvoid *) p_env, (dvoid **) &p_svc, OCI_HTYPE_SVCCTX,
(size_t) 0, (dvoid **) 0);
/* Connect to database server */
rc = OCILogon(p_env, p_err, &p_svc,
(CONST OraText *)DB_USER, (ub4)strlen((const char *)DB_USER),
(CONST OraText *)DB_PASSWORD, (ub4)strlen((const char *)DB_PASSWORD),
(CONST OraText *)DB_DBNAME, (ub4)strlen((const char *)DB_DBNAME) );
if (rc != 0) {
OCIErrorGet((dvoid *)p_err, (ub4) 1, (text *) NULL, &errcode, (OraText *)errbuf, (ub4) sizeof(errbuf), OCI_HTYPE_ERROR);
printf("Error - %.*s/n", 512, errbuf);
exit(8);
}
else
{
printf("Connect to orcl successful! /n");
}
/* Allocate and prepare SQL statement */
rc = OCIHandleAlloc((dvoid *) p_env, (dvoid **) &p_sql,
OCI_HTYPE_STMT, (size_t) 0, (dvoid **) 0);
rc = OCIStmtPrepare(p_sql, p_err, (CONST OraText *)sql,
(ub4) strlen(sql), (ub4) OCI_NTV_SYNTAX, (ub4) OCI_DEFAULT);
/* Execute the SQL statment */
rc = OCIStmtExecute(p_svc, p_sql, p_err, (ub4) 1, (ub4) 0,
(CONST OCISnapshot *) NULL, (OCISnapshot *) NULL, OCI_DEFAULT);
if(rc != OCI_SUCCESS && rc != OCI_SUCCESS_WITH_INFO){
printf("insert error!/n");
OCIErrorGet((dvoid *)p_err, (ub4) 1, (text *) NULL, &errcode, (OraText *)errbuf, (ub4) sizeof(errbuf), OCI_HTYPE_ERROR);
sprintf(out,"insert error message: %s",errbuf);
return 0;
}
else
printf("insert success!/n");
sprintf(out,"insert success!/n");
rc = OCILogoff(p_svc, p_err); /* Disconnect */
rc = OCIHandleFree((dvoid *) p_sql, OCI_HTYPE_STMT); /* Free handles */
rc = OCIHandleFree((dvoid *) p_svc, OCI_HTYPE_SVCCTX);
rc = OCIHandleFree((dvoid *) p_err, OCI_HTYPE_ERROR);
return 1;
}
int oci_query(char *sql, char *out){
/*--- initialize ---*/
OCIDATA data;
const int NUM=30;
char USER[31];
char PASS_WORD[31];
char SERVERNAME[31];
char out1[NUM];//output num 1 column
char out2[NUM];//output num 2 column
char out3[NUM];//output num 3 column
char out4[NUM];
char temp[100];
sword re;//return param
strcpy(USER,"scott");
strcpy(PASS_WORD,"tiger");
strcpy(SERVERNAME,"orcl");
/*--- get data from oracle database ---*/
ociCreatEvnHandle(&data);//initialize handle
ociLogon(&data, USER, PASS_WORD, SERVERNAME);//logon database
ociStmtPrepare(&data, sql);//prepare sql
/*--- bind data from database ---*/
ociDefineByPos(&data, 1, out1, SQLT_CHR);//bind mum 1 column
ociDefineByPos(&data, 2, out2, SQLT_CHR);//bind num 2 column
ociDefineByPos(&data, 3, out3, SQLT_CHR);//bind num 3 column
ociDefineByPos(&data, 4, out4, SQLT_CHR);//bind num 3 column
/*--- initialize output array---*/
memset(out1,0,NUM);
memset(out2,0,NUM);
memset(out3,0,NUM);
memset(out4,0,NUM);
/*--- execute sql ---*/
re = ociStmtExecute(&data);
/*--- output data from database ---*/
while(re != OCI_NO_DATA){
// printf("%s/n", out1);
sprintf(temp,"%s %s %s %s/n", out1, out2, out3,out4);
strcat(out,temp);
memset(temp,0,100);
re = ociStmtFetch(&data);
}
/*--- logout and release handles ---*/
ociHandleFree(&data);
return 1;
}
/*--- output error information ---*/
void error_proc(dvoid *errhp, sword status)
{
text errbuf[512];
sb4 errcode;
switch (status)
{
case OCI_SUCCESS:
// printf("OCI_SUCCESS/n");
break;
case OCI_SUCCESS_WITH_INFO:
printf("OCI error: OCI_SUCCESS_WITH_INFO/n");
break;
case OCI_NEED_DATA:
printf("OCI error: OCI_NEED_DATA/n");
break;
case OCI_NO_DATA:
printf("OCI error: OCI_NO_DATA/n");
break;
case OCI_ERROR:
(void)OCIErrorGet((dvoid *)errhp,(ub4)1,NULL,&errcode,
errbuf,(ub4)sizeof(errbuf),OCI_HTYPE_ERROR);
printf("....%d/n.....%s/n",errcode,errbuf);
break;
case OCI_INVALID_HANDLE:
printf("OCI error: OCI_INVALID_HANDLE/n");
break;
case OCI_STILL_EXECUTING:
printf("OCI error: OCI_STILL_EXECUTING/n");
break;
default:
break;
}
}
/*--- create env and initialize OCI handle ---*/
void ociCreatEvnHandle(OCIDATA *data){
sword re;
//......
re = OCIEnvCreate(&(data->p_env),OCI_DEFAULT,(dvoid *)0,
0,0,0,0,(dvoid **)0);
//......
re = OCIHandleAlloc((dvoid *)data->p_env, (dvoid **)&(data->p_err),
OCI_HTYPE_ERROR,0,(dvoid **)0);
if(re != 0)
printf("creation fail!");
error_proc(data->p_err, OCIHandleAlloc((dvoid *)data->p_env,
(dvoid **)&(data->p_svc), OCI_HTYPE_SVCCTX, 0, 0));
}
/*--- logon oracle database ---*/
void ociLogon(OCIDATA *data, char *user, char *pwd, char *servername){
sword status;
status = OCILogon(data->p_env, data->p_err, &(data->p_svc),
(CONST OraText *)user,
(ub4) strlen((char *)user),
(CONST OraText *)pwd,
(ub4)strlen((char *)pwd),
(CONST OraText *)servername,
(ub4)strlen((char *)servername));
if (status==OCI_SUCCESS)
printf("connection success!/n");
else {
printf("....connect fail!/n");
printf("-----ORA_search,ERROR in OCILogon-----/n");
error_proc(data->p_err,status);
}
}
/*--- prepare sql ---*/
void ociStmtPrepare(OCIDATA *data, char *strSql){
error_proc(data->p_err, OCIHandleAlloc((dvoid *)data->p_env,
(dvoid **)&(data->p_sql), OCI_HTYPE_STMT, 0, 0));
error_proc(data->p_err, OCIStmtPrepare(data->p_sql, data->p_err, (CONST OraText *)strSql,
(ub4) strlen((char *)strSql), (ub4) OCI_NTV_SYNTAX,
(ub4) OCI_DEFAULT));
}
/*--- bind data on array from database ---*/
void ociDefineByPos(OCIDATA *data, int pos, char *out, ub2 type){
error_proc(data->p_err, OCIDefineByPos(data->p_sql, &(data->p_dfn),
data->p_err, pos, (dvoid *) out, (sword)20,
type, (dvoid *) 0, (ub2 *)0, (ub2 *)0, OCI_DEFAULT));
}
/*--- execute sql ---*/
sword ociStmtExecute(OCIDATA *data){
sword status;
if ((status=OCIStmtExecute(data->p_svc, data->p_sql,
data->p_err, (ub4) 0, (ub4) 0,(CONST OCISnapshot *) NULL,
(OCISnapshot *) NULL, OCI_DEFAULT))
&& status != OCI_SUCCESS_WITH_INFO)
{ //.....
error_proc(data->p_err,status);
printf("-----ORA_search,ERROR in OCIStmtExecute-----/n");
return ERROR;
}
return status;
}
/*--- fetch data until output finish ---*/
sword ociStmtFetch(OCIDATA *data){
sword re;
re = OCIStmtFetch(data->p_sql, data->p_err, 1, 0, 0);
return re;
}
/*--- logoff and release handles ---*/
void ociHandleFree(OCIDATA *data){
OCILogoff(data->p_svc, data->p_err);
OCIHandleFree(data->p_sql, OCI_HTYPE_STMT); // Free handles
OCIHandleFree(data->p_svc, OCI_HTYPE_SVCCTX);
OCIHandleFree(data->p_err, OCI_HTYPE_ERROR);
}
5.
-- storedproc.cpp
/*****
#################### 使用OCI编写多线程的ORACLE应用软件 ###############
OCI的OCIThread软件包提供了一些线程化函数,主要有三种类型。实际使用情况见后面的编程实例。
⑴初始化和结束函数
在调用其他函数之前必须调用OCIThreadProcessInit()函数,执行OCIThread软件包的初始化工作,然后再调用OCIThreadInit()函数,初始化OCIThread上下文,供其他OCIThread函数使用。调用OCIThreadTerm()函数,结束OCIThread接口层的处理,释放OCIThread上下文内存。
⑵线程管理函数
类型为OCIThreadHandle的线程句柄用于表示线程的内部数据结构。在使用之前,应该用OCIThreadHndInit()来分配和初始化,用完后应调用OCIThreadHndDestroy()来释放内存。用OCIThreadCreate()函数创建新线程。用OCIThreadId类型变量来标识一个线程。使用OCIThreadIdInit()来分配和初始化线程ID,而用OCIThreadIdDestroy()来释放线程ID的结构。用OCIThreadClose()函数关闭线程。OCIThreadJoin()函数允许调用者线程与其他线程连接,当要想连接的线程正在运行时,阻塞调用该函数的线程。直到指定的线程运行结束,这个调用者线程才被唤醒,方能继续执行下去。
⑶互斥锁管理函数
在应用程序中用类型OCIThreadMutex的变量来表示互斥锁。互斥锁在使用之前必须用OCIThreadMutexInit()初始化,用完后要用OCIThreadMutexDestroy()释放内存结构。一个线程可用OCIThreadMutexAcquire()来掌握一把互斥锁,任何时候至多只能有一个线程掌握这把互斥锁,掌握这把互斥锁的线程能够用OCIThreadMutexRelease()来释放它。当一个线程掌握这把互斥锁后,其它线程若想再掌握这把互斥锁,就会被阻塞。直到掌握这把锁的线程释放它,被阻塞的线程之一才能得到它,获得互斥锁的线程才能继续执行下去。
下面用一个实例来讲述多线程方式ORACLE应用程序的编写和多线程的运行机制,仍以显示地震三维数据体为例。
将从数据库中读数据当作一个线程,
数据解压,三维图象处理和显示当作另一个线程,
在进程中给出二个数据缓冲区,使这二个线程轮流交叉使用这二个缓冲区。并用二把互斥锁来协调这二个线程对缓冲区的使用。
为能清楚而简单地说明线程和互斥锁的使用,这里仅给出程序的主要代码段。
*****/
#include "myoci.h"
#include <oci.h>
#include <string.h>
#include <stdio.h>
struct thrs_data {
OCIThreadMutex *mutex1;// 缓冲区1互斥锁
int buffer1[10240]; // 缓冲区1
OCIThreadMutex *mutex2;// 缓冲区2互斥锁
int buffer2[10240]; // 缓冲区2
int flag; // 数据处理结束标志
int start_read; // 开始读数据标志
int start_disp; // 开始显示数据标志
};
const int BUF_SIZE = 1024;
OCIEnv *envhp;///OCI环境句柄
OCIError *errhp;///OCI错误记录句柄
void read_fun(dvoid *arg);
void disp_fun(dvoid *arg);
int test_many_thread(void);
int main(int argc, char* argv[])
{
// test_many_thread();
char recvbuf[BUF_SIZE];
memset(recvbuf, 0, sizeof(recvbuf) );
char sendbuf[BUF_SIZE];
memset(sendbuf, 0, sizeof(sendbuf) );
strcpy(recvbuf, "INSERT INTO T VALUES (1,2,3,4) ");
oci_insert(recvbuf, sendbuf);
printf("sendbuf : %s", sendbuf);
return 0;
}
int test_many_thread(void)
{
OCIThreadId *tId1,*tId2; //线程ID句柄
OCIThreadHandle *tHnd1,*tHnd2; //线程句柄
struct thrs_data op_data; //定义数据
// OCI初始化(线程安全性)和分配句柄:
OCIEnvCreate((OCIEnv **) &envhp,OCI_THREADED,(dvoid *)0,
(dvoid* (*)(dvoid*,size_t))0,(dvoid* (*)(dvoid*,dvoid*,size_t))0,
(void (*)(dvoid *, dvoid *)) 0, (size_t) 0,(dvoid **) 0 );
OCIHandleAlloc((dvoid *)envhp, (dvoid **)&errhp,
OCI_HTYPE_ERROR,(size_t)0, (dvoid **)0);
// 线程软件包和线程初始化:
OCIThreadProcessInit();
OCIThreadInit(envhp,errhp);
// 初始化线程ID和线程句柄:
OCIThreadIdInit(envhp,errhp,&tId1);
OCIThreadHndInit(envhp,errhp,&tHnd1);
OCIThreadIdInit(envhp,errhp,&tId2);
OCIThreadHndInit(envhp,errhp,&tHnd2);
// 分配和初始化互斥锁:
OCIThreadMutexInit(envhp,errhp,&(op_data.mutex1));
OCIThreadMutexInit(envhp,errhp,&(op_data.mutex2));
// 创建新的线程,执行线程函数调用:
op_data.start_read=0;
op_data.start_disp=0;
OCIThreadCreate(envhp,errhp,read_fun,(dvoid *)&op_data, tId1,tHnd1);
OCIThreadCreate(envhp,errhp,disp_fun,(dvoid *)&op_data, tId2,tHnd2);
// 参数read_fun和disp_fun是二个线程函数,op_data是送给线程函数的变量。
// 等待线程执行完成并关闭线程句柄:
OCIThreadJoin(envhp,errhp,tHnd1);
OCIThreadClose(envhp,errhp,tHnd1);
OCIThreadJoin(envhp,errhp,tHnd2);
OCIThreadClose(envhp,errhp,tHnd2);
// 释放互斥锁内存:
OCIThreadMutexDestroy(envhp,errhp,&(op_data.mutex1));
OCIThreadMutexDestroy(envhp,errhp,&(op_data.mutex2));
// 释放线程ID和线程句柄:
OCIThreadIdDestroy(envhp,errhp,&tId1);
OCIThreadHndDestroy(envhp,errhp,&tHnd1);
OCIThreadIdDestroy(envhp,errhp,&tId2);
OCIThreadHndDestroy(envhp,errhp,&tHnd2);
// 释放线程上下文:
OCIThreadTerm(envhp,errhp);
// 释放所有分配的句柄。
OCIHandleFree((dvoid *)errhp, OCI_HTYPE_ERROR);
OCIHandleFree((dvoid *)envhp, OCI_HTYPE_ENV);
}
// 下面是二个线程函数主要代码段:
void read_fun(dvoid* arg)
{// 读数据进缓冲区函数
struct thrs_data *op_data;
int n=0;
op_data=(struct thrs_data *)arg;
for(int k=0;k<5;k++)
{ //在实际应用中,此处可为for(;;) ,让退出循环的
//条件由要读的实际数据确定,这里用5次循环,是为
//了能够运行给出的框架程序。
OCIThreadMutexAcquire(envhp,errhp,op_data->mutex1);//获得互斥锁
op_data->start_read=1;//告诉显示线程,读线程已使用缓冲区
printf("read data into buffer1 .../n");
//在实际应用中,此处应调用“读数据进缓冲区1”的函数。
OCIThreadMutexRelease(envhp,errhp,op_data->mutex1);//释放互斥锁
//在实际应用中,此处可为:当所有数据都读完时,使op_data->flag=1;并退出循环体
OCIThreadMutexAcquire(envhp,errhp,op_data->mutex2);
printf("read data into buffer2 .../n");
//在实际应用中,此处应调用“读数据进缓冲区2”的函数。
if(n==0) while(op_data->start_disp==0);//循环第一次结束时要等待显示线程启
n=1; //动并使用缓冲区
OCIThreadMutexRelease(envhp,errhp,op_data->mutex2);
if(k==2) { // 这里的代码段,是为了能演示框架程序;
op_data->flag=2; // 在实际应用中,此处可为:
break; // 当所有数据都读完时,使op_data->flag=2;
} // 并退出循环体
}
}
void disp_fun(dvoid* arg)
{ //处理和显示数据函数
struct thrs_data *op_data;
op_data=(struct thrs_data *)arg;
for(;;)
{
while(op_data->start_read==0);//开始时保证读数据线程先使用缓冲区
OCIThreadMutexAcquire(envhp,errhp,op_data->mutex1);
op_data->start_disp=1; //告诉读数据线程,显示线程已开始使用缓冲区
printf(" display buffer1 .../n");
//在实际应用中,此处应调用“使用缓冲区1中数据,解压,图象处理和显示”的函数。
OCIThreadMutexRelease(envhp,errhp,op_data->mutex1);
if(op_data->flag==1) break; //退出循环体,返回
OCIThreadMutexAcquire(envhp,errhp,op_data->mutex2);
printf(" display buffer2 .../n");
//在实际应用中,此处应调用“使用缓冲区2中数据,解压,图象处理和显示”的函数。
OCIThreadMutexRelease(envhp,errhp,op_data->mutex2);
if(op_data->flag==2) break;//退出循环体,返回
}
}
------------end------------
- 朋友托我写个OCI程序
- 自己写的oci查询程序
- 我写的第一个程序 ~~~~~~~~
- 我写的第一个ARM程序
- 朋友要我写的。
- 我排第几个---康托展开
- 找个朋友编程序
- 这个不是我写的,不过对将来想做程序的朋友会有些帮助
- 那位朋友帮忙给我写一下C语言的程序.谢谢了.. 大家好
- 帮朋友mahad写个book list。
- 一个托朋友写的SQL题,感觉还不错,分享下。
- 我的第一个完全自己写的C程序
- 我写的第一个小的程序
- 晒晒我写的第一个win32程序
- 哪个用c++帮我写个程序
- 发个我用OpengGL写的Matlab程序
- 我4年前写的第一个ruby程序
- 我在VC上写的第一个C程序
- 广义表 一些操作
- 图像配准----SIFT
- 面向对象 js 打包
- POJ 2418
- 3D游戏从头编--第一回:开发环境
- 朋友托我写个OCI程序
- 领导们的共同爱好
- 判断浏览器
- GXT TextField 实现输入大小写自动转换
- 关于String的hashCode
- flex图片剪切示例--预览、保存到本地、保存到服务器
- 3D游戏从头编--第二回:3D基本概念
- Taobao DPL
- 如何为在用用户更改默认表空间