proc*C开发(1)

本文介绍了Proc*C/C++编程方式,这是一种将SQL语句嵌入C/C++代码来操作Oracle数据库的方法。文中详细解释了其工作原理、优势及应用场景,并提供了连接数据库、插入及删除记录的具体示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

proc*C/C++是一种将SQL操作语句嵌入到c/c++代码中来操作数据库的程序开发方式。这一过程需要用到proc预编译工具。将嵌入了SQL语句的源文件转变成c/c++编译器可以解析的c/c++源文件。

很明显,这种开发方式增加了预编译这一步,增加了麻烦,于是衍生出另一个问题,这么麻烦的东西 为什么还要介绍呢?oracle相关文档给出了如下原因:
1 更方便,更简单让你的应用直接访问oarcle数据库。
2 创建高度定制化的应用。
3 可以密切监测资源利用,SQL语句的执行,以及各种运行指标。
3 调用pl/sql
4 与 其它工具相比,性能更优。这个需要对比才知道。
5 语法、语义检查。

oracle官方文档给出的优点很多,不过,除了上面第5条,其它的我都还没有深刻“领悟”到。倒是发现用proc*c/c++编码的一个缺点:难于调试,预编译时报出的错误描述难以看懂,更别说据此查找问题了。说了这么多,到底为什么学习proc*c/c++编程方式呢?对于我来说,主要是多一种研究oracle的方式。

proc*C/C++编程方式的一般流程是:
pc 文件(带嵌入的SQL 语句/过程    -------proc预编译-----&gt    *.c/*.cpp文件     ------ -c/c++编译器--- --&gt    执行文件或者库

首先,不管三七二十一,来一个简单的示例:

1 简单示例

点击(此处)折叠或打开

  1. #include <stdio.h>
  2. #include \"sqlda.h\"
  3. #include \"sqlcpr.h\"


  4. #define    SQLDESC            sqlca.sqlerrm.sqlerrmc
  5. #define    SQLDESC_LENGTH     sqlca.sqlerrm.sqlerrml

  6. /* output error message */
  7. void sql_error(struct sqlca& sqlca)
  8. {
  9.     SQLDESC[SQLDESC_LENGTH] = 0;
  10.     printf(\"%s\", SQLDESC);
  11. }

  12. /* login database */
  13. int proc_login(const char* up, const char* lsn)
  14. {
  15.     EXEC SQL BEGIN DECLARE SECTION;
  16.     char l_lsn[50];
  17.     char l_up[50];
  18.     EXEC SQL END DECLARE SECTION;

  19.     int ret(-1);
  20.     strcpy(l_up, up);
  21.     strcpy(l_lsn, lsn);

  22.     EXEC SQL WHENEVER SQLERROR do sql_error(sqlca);
  23.     EXEC SQL CONNECT :l_up using :l_lsn;

  24.     if (0 == sqlca.sqlcode)
  25.     ret = 0;

  26.     EXEC SQL WHENEVER SQLERROR continue;
  27.     return ret;
  28. }

  29. /*
  30.     insert some records
  31. */
  32. int proc_insert(int num)
  33. {
  34.     EXEC SQL BEGIN DECLARE SECTION;
  35.     int        f1;
  36.     char       f2[15];
  37.     char       f3[14]
  38.     
  39.     EXEC SQL END DECLARE SECTION;

  40.     int ret(-1);
  41.     EXEC SQL WHENEVER SQLERROR DO sql_error(sqlca);
  42.     for (int i=1; i<=num; i++)
  43.     {
  44.         f1 = i;
  45.         sprintf(f2,\"Name%d\",i);
  46.         strcpy(f3,\"bj\");


  47.         EXEC SQL INSERT INTO DEPT( DEPTNO, DNAME, LOC) VALUES(:f1, :f2, :f3);
  48.     }

  49.     EXEC SQL WHENEVER SQLERROR continue;
  50.     
  51.     EXEC SQL COMMIT;    //commit records
  52.     
  53.     return ret;
  54. }



  55. /*
  56.     delete all record
  57. */
  58. int proc_delete()
  59. {
  60.     int ret(0);

  61.     EXEC SQL WHENEVER SQLERROR DO sql_error(sqlca);
  62.     EXEC SQL delete DEPT;
  63.     EXEC SQL WHENEVER SQLERROR continue;


  64.     EXEC SQL COMMIT;
  65.     
  66.     return ret;
  67. }


  68. int main()
  69. {
  70.     //login
  71.     if (0 != proc_login("scott/tiger", "test"))
  72.     {
  73.         //error
  74.         return 1;
  75.     }
  76.     else
  77.     {
  78.         proc_insert(100);
  79.         proc_delete();        return 0;
  80.     }
  81. }

上面这段代码做了三件事:

1连接数据库:     proc_login
2插入100条记录到scott schema下的表DEPT:     proc_insert
3删除DEPT所有记录:     proc_delete

解释一下其中的一些嵌入式 SQL 语句:

嵌入SQL语句

说明                                                       

EXEC SQL BEGIN DECLARE SECTION;
EXEC SQL END DECLARE SECTION;

这两句成对使用。用来声明宿主变量的声明段,通常它们中间的宿主变量才会被proc解析和识别。

EXEC SQL WHENEVER SQLERROR do sql_error(sqlca); 
EXEC SQL WHENEVER SQLERROR continue; 

第一句的意思是:如果发生错误了就调用sql_error函数。其中sqlca这个变量由proc自动生成,
包含一个大的结构体,其状态由sqlib接口自动设定,我们一般通过它来查询执行状态,所以不要定义跟它一模一样的变量名。
第二句的意思是:如果发生错误了,只管继续(不用做什么操作)。这句话实际是对上面这一句话的重置。

通过阅读预编译后的c/c++文件,你会有深刻认识!

EXEC SQL CONNECT :l_up using :l_lsn;

这句话是连接数据库的一种方法。还有其它方式,后面可能会介绍哦:)

EXEC SQL INSERT INTO DEPT( DEPTNO, DNAME, LOC) VALUES(:f1, :f2, :f3);

插入一条记录到DEPT表中。(如此简单的一句话,预编译以后变得老长了!)

EXEC SQL COMMIT;

提交记录。

EXEC SQL delete DEPT;

删除DEPT表中所有的记录。




















2
预编译 

上面一段代码,立刻用gcc或者visual studio 编译,是通不过的。先要经过proc预编译工具转换其中的SQL语句,再才能用c/c++编译器编译。
oracle公司没有单独发布proc工具,通常需要先安装oracle服务端/客户端程序。在$ORACLE_HOME/BIN/里能找到proc工具。

假设将上面的代码保存到d:\proc_test\exam_conn.pc文件中,在windows的命令行或者linux下的terminal中均可用proc预编译它:

点击(此处)折叠或打开

  1. proc parse=none def_sqlcode=yes iname=D:\proc_test\exam_conn.pc oname=D:\proc_test\exam_conn.c
在iname指定的位置,我们将得到一个exam_conn.c文件。

首先解释一下上面用到的几个编译选项:
option 说明
parse=none 
表示只解析定义在声明段中的宿主变量。
def_sqlcode=yes
产生 '#define SQLCODE sqlca.sqlcode' 宏
iname=...
表示输入文件
oname=...   
表示输出文件 
也可以将上面的命令行写进一个文件exam_conn.cfg里。关于在vs2008中结合proc工具预编译pc文件,可以参考我的一篇博文:
http://niyirangrujiu.blog.163.com/blog/static/981733720155431833709/

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/26320972/viewspace-1688434/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/26320972/viewspace-1688434/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值