针对Oracle数据库的开发,Java和OCI是最常用的两种编程语言,对于TimesTen也是一样。
相较于Pro*C,OCI编程稍显复杂。但OCI提供更细粒度的控制,提供更丰富的功能和更好的性能。因此,对于熟悉C语言的编程人员,为性能和可控制性,以及易于调试,都应该首选OCI而非Pro*C。
和Pro*C一样, OCI也支持用TNS和easy connect string(DSN)来连接TimesTen。
可以通过connect string和TWO_TASK来指定相应的接口。
由于大部分的概念已经在 极简ProC连接TimesTen程序 中介绍,这里就不再赘述,而是直接给出源代码和Makefile。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <errno.h>
#include "tt_version.h"
#include <oci.h>
static text *crtable = "create table a(a int)";
static text *insert = "insert into a values(12345)";
static char *service = "tnssampledb_1122";
static char *username = "tthr";
static char *password = "timesten";
static OCIEnv *envhp;
static OCIError *errhp;
static OCISession *authp = (OCISession *) 0;
static OCIServer *srvhp;
static OCISvcCtx *svchp;
static void checkerr (OCIError * errhp, sword status);
int
main (int argc, char *argv[])
{
OCIStmt *stmthp, *stmthp1;
OCIEnvCreate ((OCIEnv **) & envhp, (ub4) OCI_DEFAULT,
(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);
OCIHandleAlloc ((dvoid *) envhp, (dvoid **) & srvhp, OCI_HTYPE_SERVER,
(size_t) 0, (dvoid **) 0);
OCIHandleAlloc ((dvoid *) envhp, (dvoid **) & svchp, OCI_HTYPE_SVCCTX,
(size_t) 0, (dvoid **) 0);
OCIServerAttach (srvhp, errhp, (text *) service,
strlen ((const char *) service), 0);
OCIAttrSet ((dvoid *) svchp, OCI_HTYPE_SVCCTX, (dvoid *) srvhp,
(ub4) 0, OCI_ATTR_SERVER, (OCIError *) errhp);
OCIHandleAlloc ((dvoid *) envhp, (dvoid **) & authp,
(ub4) OCI_HTYPE_SESSION, (size_t) 0, (dvoid **) 0);
OCIAttrSet ((dvoid *) authp, (ub4) OCI_HTYPE_SESSION,
(dvoid *) username, (ub4) strlen ((char *) username),
(ub4) OCI_ATTR_USERNAME, errhp);
OCIAttrSet ((dvoid *) authp, (ub4) OCI_HTYPE_SESSION,
(dvoid *) password, (ub4) strlen ((char *) password),
(ub4) OCI_ATTR_PASSWORD, errhp);
checkerr (errhp, OCISessionBegin (svchp, errhp, authp, OCI_CRED_RDBMS,
(ub4) OCI_DEFAULT));
OCIAttrSet ((dvoid *) svchp, (ub4) OCI_HTYPE_SVCCTX,
(dvoid *) authp, (ub4) 0, (ub4) OCI_ATTR_SESSION, errhp);
checkerr (errhp, OCIHandleAlloc ((dvoid *) envhp, (dvoid **) & stmthp,
OCI_HTYPE_STMT, (size_t) 0, (dvoid **) 0));
checkerr (errhp, OCIHandleAlloc ((dvoid *) envhp, (dvoid **) & stmthp1,
OCI_HTYPE_STMT, (size_t) 0, (dvoid **) 0));
checkerr (errhp, OCIStmtPrepare (stmthp, errhp, crtable,
(ub4) strlen ((char *) crtable),
(ub4) OCI_NTV_SYNTAX, (ub4) OCI_DEFAULT));
checkerr (errhp,
OCIStmtExecute (svchp, stmthp, errhp, 1, 0, 0, 0, OCI_DEFAULT));
checkerr (errhp, OCITransCommit (svchp, errhp, 0));
checkerr (errhp, OCIHandleFree ((dvoid *) stmthp, OCI_HTYPE_STMT));
checkerr (errhp, OCIStmtPrepare (stmthp1, errhp, insert,
(ub4) strlen ((char *) insert),
(ub4) OCI_NTV_SYNTAX, (ub4) OCI_DEFAULT));
checkerr (errhp,
OCIStmtExecute (svchp, stmthp1, errhp, 1, 0, 0, 0, OCI_DEFAULT));
checkerr (errhp, OCITransCommit (svchp, errhp, 0));
checkerr (errhp, OCIHandleFree ((dvoid *) stmthp1, OCI_HTYPE_STMT));
checkerr (errhp, OCISessionEnd (svchp, errhp, authp, OCI_DEFAULT));
checkerr (errhp, OCIServerDetach (srvhp, errhp, OCI_DEFAULT));
checkerr (errhp, OCIHandleFree ((dvoid *) envhp, OCI_HTYPE_ENV));
OCIHandleFree ((dvoid *) srvhp, OCI_HTYPE_ERROR);
OCIHandleFree ((dvoid *) srvhp, OCI_HTYPE_ENV);
}
static void
checkerr (OCIError * errhp, sword status)
{
text errbuf[512];
sb4 errcode = 0;
switch (status) {
case OCI_SUCCESS:
break;
case OCI_SUCCESS_WITH_INFO:
(void) printf ("Error - OCI_SUCCESS_WITH_INFO\n");
break;
case OCI_NEED_DATA:
(void) printf ("Error - OCI_NEED_DATA\n");
break;
case OCI_NO_DATA:
(void) printf ("Error - OCI_NODATA\n");
break;
case OCI_ERROR:
(void) OCIErrorGet ((dvoid *) errhp, (ub4) 1, (text *) NULL, &errcode,
errbuf, (ub4) sizeof (errbuf), OCI_HTYPE_ERROR);
(void) printf ("Error - %.*s\n", 512, (char *) errbuf);
break;
case OCI_INVALID_HANDLE:
(void) printf ("Error - OCI_INVALID_HANDLE\n");
break;
case OCI_STILL_EXECUTING:
(void) printf ("Error - OCI_STILL_EXECUTE\n");
break;
case OCI_CONTINUE:
(void) printf ("Error - OCI_CONTINUE\n");
break;
default:
break;
}
}
#
# Build TimesTen Sample Programs (Unix)
# Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
#
# $Revision
#
TT_MVL_LINUX = 0
INSTDIR = /home/oracle/TimesTen/tt1122
COMMDIR = $(INSTDIR)/quickstart/sample_code/common
TTORACLE_HOME = $(INSTDIR)/ttoracle_home/instantclient_11_2
OCIINCS = $(TTORACLE_HOME)/sdk/include
C = gcc
PLATCFLAGS = -Os -finline-functions
LDFLAGS =
INCS = -I$(OCIINCS) -I$(INSTDIR)/include -I$(COMMDIR)
CFLAGS = $(PLATCFLAGS) $(INCS) -g
TTLINK = -L$(INSTDIR)/lib -L$(TTORACLE_HOME) -Wl,-rpath,$(INSTDIR)/lib,-rpath,$(TTORACLE_HOME)
ifeq ($(TT_MVL_LINUX),1)
EXTRALIBS = -ldl -lnsl -lstdc++
endif
ICLIBS = $(TTLINK) -lc -lclntsh -lpthread -lm -lrt $(EXTRALIBS)
HELLOWORLD = helloworld
HELLOWORLDOBJS = helloworld.o
PROGS = $(HELLOWORLD) $(TPTBM) $(PLSQLOCI)
#
# Top level targets
#
all: $(PROGS)
clean:
rm -f $(PROGS) *.o
#
# Targets for building executables
#
$(HELLOWORLD): $(HELLOWORLDOBJS)
$(CC) -o $@ $(LDFLAGS) $(HELLOWORLDOBJS) $(ICLIBS)
#
# Target for building object files
#
.c.o:
$(CC) $(CFLAGS) -o $@ -c $<
可以看到,OCI的代码明显比Pro*C和Java要长,但这不是问题,因为这都是一些固定的模式,你可以将其封装成函数或定制成动态和静态链接库。
重要的是我们需要OCI提供的性能和灵活的控制。
关于Pro*C和OCI的比较,建议大家看一下 王勇 写的 Linux 操作系统下PRO*C 和OCI 程序设计分析与比较。