很明显,这种开发方式增加了预编译这一步,增加了麻烦,于是衍生出另一个问题,这么麻烦的东西 为什么还要介绍呢?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预编译-----> *.c/*.cpp文件 ------ -c/c++编译器--- --> 执行文件或者库
首先,不管三七二十一,来一个简单的示例:
1 简单示例
点击(此处)折叠或打开
- #include <stdio.h>
- #include \"sqlda.h\"
- #include \"sqlcpr.h\"
-
-
- #define SQLDESC sqlca.sqlerrm.sqlerrmc
- #define SQLDESC_LENGTH sqlca.sqlerrm.sqlerrml
-
- /* output error message */
- void sql_error(struct sqlca& sqlca)
- {
- SQLDESC[SQLDESC_LENGTH] = 0;
- printf(\"%s\", SQLDESC);
- }
-
- /* login database */
- int proc_login(const char* up, const char* lsn)
- {
- EXEC SQL BEGIN DECLARE SECTION;
- char l_lsn[50];
- char l_up[50];
- EXEC SQL END DECLARE SECTION;
-
- int ret(-1);
- strcpy(l_up, up);
- strcpy(l_lsn, lsn);
-
- EXEC SQL WHENEVER SQLERROR do sql_error(sqlca);
- EXEC SQL CONNECT :l_up using :l_lsn;
-
- if (0 == sqlca.sqlcode)
- ret = 0;
-
- EXEC SQL WHENEVER SQLERROR continue;
- return ret;
- }
-
- /*
- insert some records
- */
- int proc_insert(int num)
- {
- EXEC SQL BEGIN DECLARE SECTION;
- int f1;
- char f2[15];
- char f3[14]
-
- EXEC SQL END DECLARE SECTION;
-
- int ret(-1);
- EXEC SQL WHENEVER SQLERROR DO sql_error(sqlca);
- for (int i=1; i<=num; i++)
- {
- f1 = i;
- sprintf(f2,\"Name%d\",i);
- strcpy(f3,\"bj\");
-
-
- EXEC SQL INSERT INTO DEPT( DEPTNO, DNAME, LOC) VALUES(:f1, :f2, :f3);
- }
-
- EXEC SQL WHENEVER SQLERROR continue;
-
- EXEC SQL COMMIT; //commit records
-
- return ret;
- }
-
-
-
- /*
- delete all record
- */
- int proc_delete()
- {
- int ret(0);
-
- EXEC SQL WHENEVER SQLERROR DO sql_error(sqlca);
- EXEC SQL delete DEPT;
- EXEC SQL WHENEVER SQLERROR continue;
-
-
- EXEC SQL COMMIT;
-
- return ret;
- }
-
-
- int main()
- {
- //login
- if (0 != proc_login("scott/tiger", "test"))
- {
- //error
- return 1;
- }
- else
- {
- proc_insert(100);
- proc_delete(); return 0;
- }
- }
上面这段代码做了三件事:
2插入100条记录到scott schema下的表DEPT: proc_insert
3删除DEPT所有记录: proc_delete
解释一下其中的一些嵌入式 SQL 语句:
嵌入SQL语句 | 说明 |
EXEC SQL BEGIN DECLARE SECTION; | 这两句成对使用。用来声明宿主变量的声明段,通常它们中间的宿主变量才会被proc解析和识别。 |
EXEC SQL WHENEVER SQLERROR do sql_error(sqlca); | 第一句的意思是:如果发生错误了就调用sql_error函数。其中sqlca这个变量由proc自动生成, |
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 预编译
oracle公司没有单独发布proc工具,通常需要先安装oracle服务端/客户端程序。在$ORACLE_HOME/BIN/里能找到proc工具。
假设将上面的代码保存到d:\proc_test\exam_conn.pc文件中,在windows的命令行或者linux下的terminal中均可用proc预编译它:
点击(此处)折叠或打开
- proc parse=none def_sqlcode=yes iname=D:\proc_test\exam_conn.pc oname=D:\proc_test\exam_conn.c
首先解释一下上面用到的几个编译选项:
option | 说明 |
parse=none | 表示只解析定义在声明段中的宿主变量。 |
def_sqlcode=yes | 产生 '#define SQLCODE sqlca.sqlcode' 宏 |
iname=... | 表示输入文件 |
oname=... | 表示输出文件 |
http://niyirangrujiu.blog.163.com/blog/static/981733720155431833709/
来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/26320972/viewspace-1688434/,如需转载,请注明出处,否则将追究法律责任。
转载于:http://blog.itpub.net/26320972/viewspace-1688434/