C language to connect to Oracle databases

For many C / C ++ programmers, Oracle database operation is a technical difficulty, this paper describes the use of open-source framework freecplus Oracle database operation, freecplus framework is a C language technology network technology accumulation of two decades, powerful, easy to use.

A source code description

freecplus is a C / C ++ open source framework under a Linux system, go to the C language source code Technology Network (www.freecplus.net) download.

This article is used in connection freecplus frame type and sqlstatement operation the Oracle database.

Declaration file class is freecplus / db / oracle / _ooci.h.

Class definition file is freecplus / db / oracle / _ooci.cpp.

Sample program located freecplus / db / oracle directory.

Compiled rules file is freecplus / db / oracle / makefile.

Second, an overview

This article does not cover the Oracle database, SQL language and C / C ++ basics, you should be a professional C / C ++ programmer, before reading this article, you have mastered the basics of the Oracle database and SQL language.

Oracle Database powerful, superior performance, unmatched, and provides data access interface OCI, OCI very strong, strong enough to ordinary C / C ++ programmers difficult to manage.

The frame freecplus OCI (Oracle Call Interface) connection and sqlstatement packaged in a class, the class of operations using an Oracle database package, the code simple and elegant, superior performance.

Then I will declare connection and sqlstatement class list, and then introduce the use of its site by the flow chart and sample programs.

Three, connection type

Oracle database connection pool connection declaration class (private member data structure and the programmer does not have to be concerned about are not listed):

// Oracle数据库连接池类。
class connection
{
public:
  int m_state;       // 与数据库的连接状态,0-未连接,1-已连接。

  CDA_DEF m_cda;       // 数据库操作的结果或最后一次执行SQL语句的结果。

  char m_sql[10241];   // SQL语句的文本,最长不能超过10240字节。

  connection();    // 构造函数。
 ~connection();    // 析构函数。

  // 登录数据库。
  // connstr:数据库的登录参数,格式:username/password@tnsname,username-用户名,password-登录密
  // 码,tnsname-数据库的服务名,在$ORACLE_HOME/network/admin/tnsnames.ora文件中配置。
  // charset:数据库的字符集,必须与数据库保持一致,否则会出现中文乱码的情况。
  // autocommitopt:是否启用自动提交,0-不启用,1-启用,缺省是不启用。
  // 返回值:0-成功,其它失败,失败的代码在m_cda.rc中,失败的描述在m_cda.message中。
  int connecttodb(char *connstr,char *charset,int autocommitopt=0);

  // 提交事务。
  // 返回值:0-成功,其它失败,程序员一般不必关心返回值。
  int commit(); 

  // 回滚事务。
  // 返回值:0-成功,其它失败,程序员一般不必关心返回值。
  int  rollback();

  // 断开与数据库的连接。
  // 注意,断开与数据库的连接时,全部未提交的事务自动回滚。
  // 返回值:0-成功,其它失败,程序员一般不必关心返回值。
  int disconnect();

  // 执行SQL语句。
  // 如果SQL语句不需要绑定输入和输出变量(无绑定变量、非查询语句),可以直接用此方法执行。
  // 参数说明:这是一个可变参数,用法与printf函数相同。
  // 返回值:0-成功,其它失败,失败的代码在m_cda.rc中,失败的描述在m_cda.message中,
  // 如果成功的执行了非查询语句,在m_cda.rpc中保存了本次执行SQL影响记录的行数。
  // 程序员必须检查execute方法的返回值。
  // 在connection类中提供了execute方法,是为了方便程序员,在该方法中,也是用sqlstatement类来完成功能。
  int execute(const char *fmt,...);
};

Four, sqlstatement class

Statement SQL statements to manipulate sqlstatement class Oracle database (private member data structure and the programmer does not have to be concerned about is not listed, the method of CLOB and BLOB field operations also are not listed):

// 操作SQL语句类。
class sqlstatement
{
  OCI_HANDLE m_handle; // SQL句柄。
  connection *m_conn;  // 数据库连接池指针。
  int m_sqltype;       // SQL语句的类型,0-查询语句;1-非查询语句。
  int m_autocommitopt; // 自动提交标志,0-关闭;1-开启。
  void err_report();   // 错误报告。

  OCILobLocator *m_lob;     // 指向LOB字段的指针。
  int  alloclob();          // 初始化lob指针。
  int  filetolob(FILE *fp); // 把文件的内容导入到clob和blob字段中。
  int  lobtofile(FILE *fp); // 从clob和blob字段中导出内容到文件中。
  void freelob();           // 释放lob指针。
public:
  int m_state;         // 与数据库连接池的绑定状态,0-未绑定,1-已绑定。

  char m_sql[10241];   // SQL语句的文本,最长不能超过10240字节。

  CDA_DEF m_cda;       // 执行SQL语句的结果。

  sqlstatement();      // 构造函数。
  sqlstatement(connection *conn);    // 构造函数,同时绑定数据库连接池。

 ~sqlstatement();

  // 绑定数据库连接池。
  // conn:数据库连接池connection对象的地址。
  // 返回值:0-成功,其它失败,只要conn参数是有效的,并且数据库的游标资源足够,connect方法不会返回失败。
  // 程序员一般不必关心connect方法的返回值。
  // 注意,每个sqlstatement只需要绑定一次,在绑定新的connection前,必须先调用disconnect方法。
  int connect(connection *conn); 

  // 取消与数据库连接池的绑定。
  // 返回值:0-成功,其它失败,程序员一般不必关心返回值。
  int disconnect();

  // 准备SQL语句。
  // 参数说明:这是一个可变参数,用法与printf函数相同。
  // 返回值:0-成功,其它失败,程序员一般不必关心返回值。
  // 注意:如果SQL语句没有改变,只需要prepare一次就可以了。
  int prepare(const char *fmt,...);

  // 绑定输入变量的地址。
  // position:字段的顺序,从1开始,必须与prepare方法中的SQL的序号一一对应。
  // value:输入变量的地址,如果是字符串,内存大小应该是表对应的字段长度加1。
  // len:如果输入变量的数据类型是字符串,用len指定它的最大长度,建议采用表对应的字段长度。
  // 返回值:0-成功,其它失败,程序员一般不必关心返回值。
  // 注意:如果SQL语句没有改变,只需要bindin一次就可以了。
  int bindin(unsigned int position,int    *value);
  int bindin(unsigned int position,long   *value);
  int bindin(unsigned int position,unsigned int  *value);
  int bindin(unsigned int position,unsigned long *value);
  int bindin(unsigned int position,float *value);
  int bindin(unsigned int position,double *value);
  int bindin(unsigned int position,char   *value,unsigned int len);

  // 绑定输出变量的地址。
  // position:字段的顺序,从1开始,与SQL的结果集一一对应。
  // value:输出变量的地址,如果是字符串,内存大小应该是表对应的字段长度加1。
  // len:如果输出变量的数据类型是字符串,用len指定它的最大长度,建议采用表对应的字段长度。
  // 返回值:0-成功,其它失败,程序员一般不必关心返回值。
  // 注意:如果SQL语句没有改变,只需要bindout一次就可以了。
  int bindout(unsigned int position,int    *value);
  int bindout(unsigned int position,long   *value);
  int bindout(unsigned int position,unsigned int  *value);
  int bindout(unsigned int position,unsigned long *value);
  int bindout(unsigned int position,float *value);
  int bindout(unsigned int position,double *value);
  int bindout(unsigned int position,char   *value,unsigned int len);

  // 执行SQL语句。
  // 返回值:0-成功,其它失败,失败的代码在m_cda.rc中,失败的描述在m_cda.message中。
  // 如果成功的执行了非查询语句,在m_cda.rpc中保存了本次执行SQL影响记录的行数。
  // 程序员必须检查execute方法的返回值。
  int execute();
  
  // 执行SQL语句。
  // 如果SQL语句不需要绑定输入和输出变量(无绑定变量、非查询语句),可以直接用此方法执行。
  // 参数说明:这是一个可变参数,用法与printf函数相同。
  // 返回值:0-成功,其它失败,失败的代码在m_cda.rc中,失败的描述在m_cda.message中,
  // 如果成功的执行了非查询语句,在m_cda.rpc中保存了本次执行SQL影响记录的行数。
  // 程序员必须检查execute方法的返回值。
  int execute(const char *fmt,...);

  // 从结果集中获取一条记录。
  // 如果执行的SQL语句是查询语句,调用execute方法后,会产生一个结果集(存放在数据库的缓冲区中)。
  // next方法从结果集中获取一条记录,把字段的值放入已绑定的输出变量中。
  // 返回值:0-成功,1403-结果集已无记录,其它-失败,失败的代码在m_cda.rc中,失败的描述在m_cda.message中。
  // 返回失败的原因主要有两个:1)与数据库的连接已断开;2)绑定输出变量的内存太小。
  // 每执行一次next方法,m_cda.rpc的值加1。
  // 程序员必须检查next方法的返回值。
  int next();
};

Fifth, the program flow

freecplus framework for the operation of the Oracle database SQL statement is divided into two types: There are a result set of SQL statements and SQL statements without result sets.

If the SQL statement is executed, it produces the result set, called the result sets of SQL, that is, data query language DQL, to select a keyword, a variety of simple queries, join queries belong DQL.

If the SQL statement is executed, the result set is not generated, the result set is referred to as a non-SQL, including the DDL data definition language (mainly create, drop and ALTER) and data manipulation language DML (insert, update and insert).

You can also say, the query will produce a result set of SQL statements, other SQL statements will not produce a result set.

Process 1, no result set of SQL procedures

Here Insert Picture Description

This is a complete way of the process, in the actual development, if it is to perform simple SQL statements, Step 6 and Step 7 may not be necessary, if the SQL statement is executed only once between cycles, Step 7 and Step 8 You do not need.

Process 2, a result set of SQL procedures

Here Insert Picture Description
This is a complete way of the process, in the actual development, if it is to perform simple queries, Step 6, Step 7 and Step 8 may not be necessary, if the result set up to only one record, step 10 and 11 cycling between steps do not need.

Sixth, the sample program

1, create a super-woman information table

Example (createtable.cpp)

/*
 *  程序名:createtable.cpp,此程序演示freecplus框架操作Oracle数据库(创建表)。
 *  作者:C语言技术网(www.freecplus.net) 日期:20190525
*/
#include "_ooci.h"   // freecplus框架操作Oracle的头文件。

int main(int argc,char *argv[])
{
  connection conn; // 数据库连接类

  // 登录数据库,返回值:0-成功,其它-失败。
  // 失败代码在conn.m_cda.rc中,失败描述在conn.m_cda.message中。
  if (conn.connecttodb("scott/tiger@snorcl11g_198","Simplified Chinese_China.ZHS16GBK")!=0)
  {
    printf("connect database failed.\n%s\n",conn.m_cda.message); return -1;
  }
  
  sqlstatement stmt(&conn); // 操作SQL语句的对象。

  // 准备创建表的SQL语句。
  // 超女表girls,超女编号id,超女姓名name,体重weight,报名时间btime,超女说明memo,超女图片pic。
  stmt.prepare("\
    create table girls(id    number(10),\
                       name  varchar2(30),\
                       weight   number(8,2),\
                       btime date,\
                       memo  clob,\
                       pic   blob,\
                       primary key (id))");
  // prepare方法不需要判断返回值。

  // 执行SQL语句,一定要判断返回值,0-成功,其它-失败。
  // 失败代码在stmt.m_cda.rc中,失败描述在stmt.m_cda.message中。
  if (stmt.execute() != 0)
  {
    printf("stmt.execute() failed.\n%s\n%s\n",stmt.m_sql,stmt.m_cda.message); return -1;
  }

  printf("create table girls ok.\n");
}

running result

Here Insert Picture Description

2, 5 is inserted into the recording table Super Girl

Example (inserttable.cpp)

/*
 *  程序名:inserttable.cpp,此程序演示freecplus框架操作Oracle数据库(向表中插入5条记录)。
 *  作者:C语言技术网(www.freecplus.net) 日期:20190525
*/
#include "_ooci.h"   // freecplus框架操作Oracle的头文件。

// 定义用于超女信息的结构,与表中的字段对应。
struct st_girls
{
  long id;        // 超女编号,用long数据类型对应Oracle无小数的number(10)。
  char name[11];  // 超女姓名,用char[31]对应Oracle的varchar2(30)。
  double weight;  // 超女体重,用double数据类型对应Oracle有小数的number(8,2)。
  char btime[20]; // 报名时间,用char对应Oracle的date,格式:'yyyy-mm-dd hh24:mi:ssi'。
} stgirls;

int main(int argc,char *argv[])
{
  connection conn; // 数据库连接类

  // 登录数据库,返回值:0-成功,其它-失败。
  // 失败代码在conn.m_cda.rc中,失败描述在conn.m_cda.message中。
  if (conn.connecttodb("scott/tiger@snorcl11g_198","Simplified Chinese_China.ZHS16GBK")!=0)
  {
    printf("connect database failed.\n%s\n",conn.m_cda.message); return -1;
  }
  
  sqlstatement stmt(&conn); // 操作SQL语句的对象。

  // 准备插入表的SQL语句。
  stmt.prepare("\
    insert into girls(id,name,weight,btime) \
                values(:1,:2,:3,to_date(:4,'yyyy-mm-dd hh24:mi:ss'))");
  // prepare方法不需要判断返回值。
  // 为SQL语句绑定输入变量的地址,bindin方法不需要判断返回值。
  stmt.bindin(1,&stgirls.id);
  stmt.bindin(2, stgirls.name,10);
  stmt.bindin(3,&stgirls.weight);
  stmt.bindin(4, stgirls.btime,19);

  // 模拟超女数据,向表中插入5条测试信息。
  for (int ii=1;ii<=5;ii++)
  {
    memset(&stgirls,0,sizeof(stgirls)); // 结构体变量初始化。

    // 为结构体变量的成员赋值。
    stgirls.id=ii;                                 // 超女编号。
    sprintf(stgirls.name,"超女%02d",ii);           // 超女姓名。
    stgirls.weight=ii*2.11;                        // 超女体重。
    strcpy(stgirls.btime,"2018-03-01 12:25:31");   // 报名时间。

    // 执行SQL语句,一定要判断返回值,0-成功,其它-失败。
    // 失败代码在stmt.m_cda.rc中,失败描述在stmt.m_cda.message中。
    if (stmt.execute() != 0)
    {
      printf("stmt.execute() failed.\n%s\n%s\n",stmt.m_sql,stmt.m_cda.message); return -1;
    }

    printf("成功插入了%ld条记录。\n",stmt.m_cda.rpc); // stmt.m_cda.rpc是本次执行SQL影响的记录数。
  }

  printf("insert table girls ok.\n");

  conn.commit(); // 提交数据库事务。
}

running result

Here Insert Picture Description

3, update records in the table Super Girl

Example (updatetable.cpp)

/*
 *  程序名:updatetable.cpp,此程序演示freecplus框架操作Oracle数据库(修改表中的记录)。
 *  作者:C语言技术网(www.freecplus.net) 日期:20190525
*/
#include "_ooci.h"   // freecplus框架操作Oracle的头文件。

int main(int argc,char *argv[])
{
  connection conn; // 数据库连接类

  // 登录数据库,返回值:0-成功,其它-失败。
  // 失败代码在conn.m_cda.rc中,失败描述在conn.m_cda.message中。
  if (conn.connecttodb("scott/tiger@snorcl11g_198","Simplified Chinese_China.ZHS16GBK")!=0)
  {
    printf("connect database failed.\n%s\n",conn.m_cda.message); return -1;
  }

  sqlstatement stmt(&conn); // 操作SQL语句的对象。

  char strbtime[20];  // 用于存放超女的报名时间。
  memset(strbtime,0,sizeof(strbtime));
  strcpy(strbtime,"2019-12-20 09:45:30");

  // 准备更新数据的SQL语句,不需要判断返回值。
  stmt.prepare("\
    update girls set btime=to_date(:1,'yyyy-mm-dd hh24:mi:ss') where id>=2 and id<=4");
  // prepare方法不需要判断返回值。
  // 为SQL语句绑定输入变量的地址,bindin方法不需要判断返回值。
  stmt.bindin(1,strbtime,19);
  // 如果不采用绑定输入变量的方法,把strbtime的值直接写在SQL语句中也是可以的,如下:
  /*
  stmt.prepare("\
    update girls set btime=to_date('%s','yyyy-mm-dd hh24:mi:ss') where id>=2 and id<=4",strbtime);
  */

  // 执行SQL语句,一定要判断返回值,0-成功,其它-失败。
  // 失败代码在stmt.m_cda.rc中,失败描述在stmt.m_cda.message中。
  if (stmt.execute() != 0)
  {
    printf("stmt.execute() failed.\n%s\n%s\n",stmt.m_sql,stmt.m_cda.message); return -1;
  }

  // 请注意,stmt.m_cda.rpc变量非常重要,它保存了SQL被执行后影响的记录数。
  printf("本次更新了girls表%ld条记录。\n",stmt.m_cda.rpc);

  // 提交事务
  conn.commit();
}

running result

Here Insert Picture Description

4, Super Girl query log table

Example (selecttable.cpp)

/*
 *  程序名:selecttable.cpp,此程序演示freecplus框架操作Oracle数据库(查询表中的记录)。
 *  作者:C语言技术网(www.freecplus.net) 日期:20190525
*/
#include "_ooci.h"   // freecplus框架操作Oracle的头文件。

// 定义用于超女信息的结构,与表中的字段对应。
struct st_girls
{
  long id;        // 超女编号,用long数据类型对应Oracle无小数的number(10)。
  char name[31];  // 超女姓名,用char[31]对应Oracle的varchar2(30)。
  double weight;  // 超女体重,用double数据类型对应Oracle有小数的number(8,2)。
  char btime[20]; // 报名时间,用char对应Oracle的date,格式:'yyyy-mm-dd hh24:mi:ss'。
} stgirls;

int main(int argc,char *argv[])
{
  connection conn; // 数据库连接类
  
  // 登录数据库,返回值:0-成功,其它-失败。
  // 失败代码在conn.m_cda.rc中,失败描述在conn.m_cda.message中。
  if (conn.connecttodb("scott/tiger@snorcl11g_198","Simplified Chinese_China.ZHS16GBK")!=0)
  {
    printf("connect database failed.\n%s\n",conn.m_cda.message); return -1;
  }

  sqlstatement stmt(&conn); // 操作SQL语句的对象。

  int iminid,imaxid;  // 查询条件最小和最大的id。

  // 准备查询表的SQL语句。
  stmt.prepare("\
    select id,name,weight,to_char(btime,'yyyy-mm-dd hh24:mi:ss') from girls where id>=:1 and id<=:2");
  // prepare方法不需要判断返回值。
  // 为SQL语句绑定输入变量的地址,bindin方法不需要判断返回值。
  stmt.bindin(1,&iminid);
  stmt.bindin(2,&imaxid);
  // 为SQL语句绑定输出变量的地址,bindout方法不需要判断返回值。
  stmt.bindout(1,&stgirls.id);
  stmt.bindout(2, stgirls.name,30);
  stmt.bindout(3,&stgirls.weight);
  stmt.bindout(4, stgirls.btime,19);

  iminid=2;  // 指定待查询记录的最小id的值。
  imaxid=4;  // 指定待查询记录的最大id的值。

  // 执行SQL语句,一定要判断返回值,0-成功,其它-失败。
  // 失败代码在stmt.m_cda.rc中,失败描述在stmt.m_cda.message中。
  if (stmt.execute() != 0)
  {
    printf("stmt.execute() failed.\n%s\n%s\n",stmt.m_sql,stmt.m_cda.message); return -1;
  }

  // 本程序执行的是查询语句,执行stmt.execute()后,将会在数据库的缓冲区中产生一个结果集。
  while (1)
  {
    memset(&stgirls,0,sizeof(stgirls)); // 先把结构体变量初始化。

    // 从结果集中获取一条记录,一定要判断返回值,0-成功,1403-无记录,其它-失败。
    // 在实际开发中,除了0和1403,其它的情况极少出现。
    if (stmt.next() !=0) break;
    
    // 把获取到的记录的值打印出来。
    printf("id=%ld,name=%s,weight=%.02f,btime=%s\n",stgirls.id,stgirls.name,stgirls.weight,stgirls.btime);
  }

  // 请注意,stmt.m_cda.rpc变量非常重要,它保存了SQL被执行后影响的记录数。
  printf("本次查询了girls表%ld条记录。\n",stmt.m_cda.rpc);
}

running result

Here Insert Picture Description

5, Super Girl query the number of records in the table

Example (counttable.cpp)

/*
 *  程序名:counttable.cpp,此程序演示freecplus框架操作Oracle数据库(查询表中的记录数)。
 *  作者:C语言技术网(www.freecplus.net) 日期:20190525
*/
#include "_ooci.h"   // freecplus框架操作Oracle的头文件。

int main(int argc,char *argv[])
{
  connection conn; // 数据库连接类
  
  // 登录数据库,返回值:0-成功,其它-失败。
  // 失败代码在conn.m_cda.rc中,失败描述在conn.m_cda.message中。
  if (conn.connecttodb("scott/tiger@snorcl11g_198","Simplified Chinese_China.ZHS16GBK")!=0)
  {
    printf("connect database failed.\n%s\n",conn.m_cda.message); return -1;
  }

  sqlstatement stmt(&conn); // 操作SQL语句的对象。

  int icount=0;  // 用于存放查询结果的记录数。

  // 准备查询表的SQL语句,把查询条件直接写在SQL语句中,没有采用绑定输入变量的方法。
  stmt.prepare("select count(*) from girls where id>=2 and id<=4");
  // prepare方法不需要判断返回值。
  // 为SQL语句绑定输出变量的地址,bindout方法不需要判断返回值。
  stmt.bindout(1,&icount);

  // 执行SQL语句,一定要判断返回值,0-成功,其它-失败。
  // 失败代码在stmt.m_cda.rc中,失败描述在stmt.m_cda.message中。
  if (stmt.execute() != 0)
  {
    printf("stmt.execute() failed.\n%s\n%s\n",stmt.m_sql,stmt.m_cda.message); return -1;
  }

  // 本程序执行的是查询语句,执行stmt.execute()后,将会在数据库的缓冲区中产生一个结果集。
  // 但是,在本程序中,结果集永远只有一条记录,调用stmt.next()一次就行,不需要循环。
  stmt.next();
  
  printf("girls表中符合条件的记录数是%d。\n",icount);
}

running result

Here Insert Picture Description

7, delete records in the table Super Girl

Example (deletetable.cpp)

/*
 *  程序名:deletetable.cpp,此程序演示freecplus框架操作Oracle数据库(删除表中的记录)。
 *  作者:C语言技术网(www.freecplus.net) 日期:20190525
*/
#include "_ooci.h"   // freecplus框架操作Oracle的头文件。

int main(int argc,char *argv[])
{
  connection conn; // 数据库连接类

  // 登录数据库,返回值:0-成功,其它-失败。
  // 失败代码在conn.m_cda.rc中,失败描述在conn.m_cda.message中。
  if (conn.connecttodb("scott/tiger@snorcl11g_198","Simplified Chinese_China.ZHS16GBK")!=0)
  {
    printf("connect database failed.\n%s\n",conn.m_cda.message); return -1;
  }

  sqlstatement stmt(&conn); // 操作SQL语句的对象。

  // 执行SQL语句,一定要判断返回值,0-成功,其它-失败。
  // 失败代码在stmt.m_cda.rc中,失败描述在stmt.m_cda.message中。
  // 如果不需要绑定输入和输出变量,用stmt.execute()方法直接执行SQL语句,不需要stmt.prepare()。
  if (stmt.execute("delete from girls where id>=2 and id<=4") != 0)
  {
    printf("stmt.execute() failed.\n%s\n%s\n",stmt.m_sql,stmt.m_cda.message); return -1;
  }

  // 请注意,stmt.m_cda.rpc变量非常重要,它保存了SQL被执行后影响的记录数。
  printf("本次从girls表中删除了%ld条记录。\n",stmt.m_cda.rpc); 

  // 提交事务
  conn.commit();
}

running result

Here Insert Picture Description

8, execute PL / SQL procedure

Example (execplsql.cpp)

/*
 *  程序名:execplsql.cpp,此程序演示freecplus框架操作Oracle数据库(执行PL/SQL过程)。
 *  作者:C语言技术网(www.freecplus.net) 日期:20190525
 *  说说我个人的看法,我从不在Oracle数据库中创建PL/SQL过程,也很少使用触发器,原因如下:
 *  1、在Oracle数据库中创建PL/SQL过程,程序的调试很麻烦;
 *  2、维护工作很麻烦,因为维护人员要花时间去了解数据库中的存储过程;
 *  3、采用freecplus框架操作Oracle已经是非常简单,没必要去折腾存储过程;
 *  4、PL/SQL过程可移植性不好,如果换成mysql或其它数据库,比较麻烦。
 *  还有,我在C/C++程序中很少用复杂的PL/SQL过程,因为复杂的PL/SQL调试麻烦。
*/
#include "_ooci.h"   // freecplus框架操作Oracle的头文件。

int main(int argc,char *argv[])
{
  connection conn; // 数据库连接类

  // 登录数据库,返回值:0-成功,其它-失败。
  // 失败代码在conn.m_cda.rc中,失败描述在conn.m_cda.message中。
  if (conn.connecttodb("scott/tiger@snorcl11g_198","Simplified Chinese_China.ZHS16GBK")!=0)
  {
    printf("connect database failed.\n%s\n",conn.m_cda.message); return -1;
  }

  sqlstatement stmt(&conn); // 操作SQL语句的对象。

  int id=100;

  // 准备查询表的PL/SQL语句,先删除girls表中的全部记录,再插入一条记录。
  stmt.prepare("\
    BEGIN\
      delete from girls;\
      insert into girls(id,name,weight,btime)\
                 values(:1,'超女过程',55.65,to_date('2018-01-02 13:00:55','yyyy-mm-dd hh24:mi:ss'));\
    END;");
  // 注意,PL/SQL中的每条SQL需要用分号结束,END之后还有一个分号。
  // prepare方法不需要判断返回值。
  // 为PL/SQL语句绑定输入变量的地址,bindin方法不需要判断返回值。
  stmt.bindin(1,&id);
  
  // 执行SQL语句,一定要判断返回值,0-成功,其它-失败。
  if (stmt.execute() != 0)
  {
    printf("stmt.execute() failed.\n%s\n%s\n",stmt.m_sql,stmt.m_cda.message); return -1;
  }

  printf("exec PL/SQL ok.\n");

  // 提交事务。
  conn.commit();
}

running result

Here Insert Picture Description

9, the operation and BLOB fields CLOB

sqlstatement class can also operate CLOB and BLOB field, in the actual development, much of this demand, we will not demonstrate, if you have needs in this area in project development, reference may demo program, sample program located freecplus / db / oracle directory, as follows:

filetoclob.cpp: the text file into a CLOB field in the data table.

clobtofile.cpp: the contents of the data table CLOB field is exported to a text file.

filetoblob.cpp: the text file into BLOB field in the data table.

blobtofile.cpp: the contents of the data table BLOB field is exported to a text file.

Eight, application experience

freecplus framework of the connection and the power of sqlstatement class OCI fully play out, and superior performance. This article provides a sample program looks simple, but actually very sophisticated, hope a lot of thinking, gradually began to feel.

In order for us to fully grasp the connection and usage sqlstatement class, I will record video freecplus thematic framework, please pay more attention to the content of C Language Technology Network (www.freecplus.net) release.

Seven, copyright notice

C Language Technology Network original article, reproduced please indicate the source link to the article, the author and original.
Source: C Language Technology Network (www.freecplus.net)
Author: Ethics code Agriculture

Guess you like

Origin www.cnblogs.com/wucongzhou/p/12613241.html