极简OCI连接TimesTen程序

针对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。

helloworld.c程序

#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;
  }
}

Makefile

#
# 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 程序设计分析与比较。

你可能感兴趣的:(C语言,oci,timesten)