OTL调用存储过程/函数及注意事项
OTL 是 Oracle, Odbc and DB2-CLI Template Library 的缩写,是一个 C++ 编译中操控关系数据库的模板库,它目前几乎支持所有的当前各种主流数据库。 OTL 使用起来比较方便,其官方网站也提供了详细的文档和例子( http://otl.sourceforge.net/otl3.htmhttp://otl.sourceforge.net/otl3_examples.htm )。
最近在项目中需要使用 OTL 调用 Oracle 存储过程,并且需要返回游标,在网上查了一下,相关的中文资料比较少,经过一番辛苦的查找和摸索,最后终于如愿达到目的。在这里把相关的经验分享给大家,如有不对的地方,欢迎拍砖。
OTL 调用 Oracle 存储过程,其官方文档中给出了相应的例子,地址是 http://otl.sourceforge.net/otl4_ex149.htm 。现节选关键部分如下:
…
otl_stream i(1,
"begin "
" my_pkg.my_proc(:f1<int,in>,:f2<int,in>, "
" :str1<char[100],out>, "
" :cur1<refcur,out[50]>, "
" :cur2<refcur,out[50]>); "
"end;",
db // connect object
);
i.set_commit(0); // set stream "auto-commit" to OFF.
char str1[101];
float f1;
char f2[31];
otl_refcur_stream s1, s2; // reference cursor streams for reading rows.
i<<8<<4;
i>>str1;
i>>s1;
i>>s2;
cout<<"STR1="<<str1<<endl;
cout<<"=====> Reading :cur1..."<<endl;
while(!s1.eof()){ // while not end-of-data
s1>>f1>>f2;
cout<<"f1="<<f1<<", f2="<<f2<<endl;
}
cout<<"=====> Reading :cur2..."<<endl;
while(!s2.eof()){ // while not end-of-data
s2>>f1>>f2;
cout<<"f1="<<f1<<", f2="<<f2<<endl;
}
s1.close(); // closing the reference cursor
s2.close(); // closing the reference cursor
…
可以看出,调用存储过程和执行普通的 sql 大同小异,也是通过 otl_stream 对象绑定相关参数,不同之处有以下几点:
1 .调用存储过程 / 函数时,缓冲大小必须设置为 1 。
2 . Sql 声明时语句必须采用 ”begin …… end;” 的形式。存储过程如果位于包内,还必须带上包名。绑定参数除了声明类型、大小以外,还必须指明参数的输入输出标志。返回游标的大小代表了游标内的记录数。
3 .返回游标绑定的数据类型是 otl_refcur_stream ,就像普通的 otl_stream 一样,可以使用 while 循环读取其中的数据。游标对象使用完毕后,别忘了使用 close 方法将其关闭。
在这个过程中,有两个需要注意的地方:
1 . OTL 在输入输出参数的方向标志方面稍微有点不人性化,即要求所有的 in 、 out 与前面的逗号“ , ”之间不允许有空格、制表符等空白字符,否则就会无法识别方向标志而发生 ORA-01008 错误,并提示“并非所有变量都已绑定”。
2 .如果存储过程内存在多条执行路径,并且某些执行路径并不返回游标的情况下,就需要程序员自己判断在当前情况下是否需要接收游标。如果当前存储过程并未返回游标,而在 c++ 程序中执行了提取( >> )操作,就会发生 ORA-24338 错误 ,并提示“未执行语句句柄”。此时,如果允许的话可以通过存储过程返回的其他变量判断是否需要进行接收操作,如:
…
if(“00” == ret_code) // 其中 ret_code 是存接收了储过程执行状态的变量
{
o >> first_cur;
o >> detail_cur;
}
…
OTL 调用存储函数和存储过程基本相似,只不过是多了一个返回值而以。格式大致如下:
…
otl_stream i(1,
"begin "
" :rc<int,out> :=my_pkg. my_func(:f1<int,in>,:f2<int,in>, "
" :str1<char[100],out>, "
" :cur1<refcur,out[50]>, "
" :cur2<refcur,out[50]> "
" ); "
" end; ",
db // connect object
);
int res = 0;
char str1[101];
float f1;
char f2[31];
otl_refcur_stream s1, s2; // reference cursor streams for reading rows.
i<<8<<4;
i >> res;
i>>str1;
i>>s1;
i>>s2;
…
这里也有两个需要注意的地方,一是 sql 声明时存储函数名前面的等号要用“ := ”;再就是接收输出时,首先接收函数返回值,再依次接收其他输出。其他操作同存储过程一致。关于调用存储过程 / 函数时, sql 声明的具体格式, OTL 提供了一个专门的函数create_stored_proc_call ,可以生成相应的绑定 sql 。其具体使用方法参见 http://otl.sourceforge.net/otl4_ex153.htm 。
补充一下:笔者的环境是 otl v4.0.218 OraClient11g vs2008sp1 winxp sp3 。
OTL调用存储过程/函数及注意事项的更多相关文章
- DAO调用存储过程问题
相关文章:1.使用 Spring 框架调用 DB2 存储过程 2.Spring如何使用JdbcTemplate调用存储过程的三种情况 3.spring中调用存储过程,函数
- MySQL 存储过程 函数 routine 权限
MySQL 存储过程 函数 routine 权限 Table of Contents 1. mysql存储过程/函数权限 1.1. 相关对象操作权限检查 1.2. 执行权限 1 mysql存储过程/函 ...
- jdbc调用存储过程和函数
1.调用存储过程 public class CallOracleProc { public static void main(String[] args) throws Exception{ Stri ...
- java调用存储过程和函数
以对表test进行增,删,改,查进行说明:1.新建表test create table TEST ( TID NUMBER not null, TNAME VARCHAR2(32), TCODE VA ...
- 转:EF调用存储过程、函数
EF调用存储过程.函数 2014-04-02 09:12:20| 分类: ORM框架|举报|字号 订阅 一.ef4.1 codeFirst 修改表结构 增加字段等 EF code ...
- 【转】java调用存储过程和函数
一.概述 如果想要执行存储过程,我们应该使用 CallableStatement 接口. CallableStatement 接口继承自PreparedStatement 接口.所以CallableS ...
- JDBC第二篇--【PreparedStatment、批处理、处理二进制、自动主键、调用存储过程、函数】
这是我JDBC的第一篇 http://blog.csdn.net/hon_3y/article/details/53535798 1.PreparedStatement对象 PreparedState ...
- java程序调用存储过程和存储函数
java程序调用存储过程 jdbcUtil.java文件 package cn.itcast.oracle.utils; import java.sql.Connection; import java ...
- oracle创建函数和调用存储过程和调用函数的例子(区别)
创建函数: 格式:create or replace function func(参数 参数类型) Return number Is Begin --------业务逻辑--------- End; ...
随机推荐
- mybatis官网学习
javaType:一个 Java 类的完全限定名,或一个类型别名(参考上面内建类型别名 的列表) .如果你映射到一个 JavaBean,MyBatis 通常可以断定类型. 然而,如果你映射到的是 Ha ...
- 【hdoj_2187】老人是真饿了
题目:http://acm.hdu.edu.cn/showproblem.php?pid=2187 题意:由很多种价格的大米,在经费一定的情况下,买重量更多的大米,并且题目假设经费买不光所有的大米. ...
- react native native module
React Native Native Modules,官方地址:https://facebook.github.io/react-native/docs/native-modules-android ...
- linux 挂载 ip-SAN
linux 挂载 ip-SAN 如何在 SAN 里面分配块就不讲了 # 安装 iscsi 工具 yum install iscsi-initiator-utils # 启动相关的服务 systemct ...
- onethink 路由规则无效问题解决
修改文件 Application/Common/Conf/config.php 打开注释 //'MODULE_ALLOW_LIST' => array('Home','Admin'), // 1 ...
- mysql查看表结构,字段等命令
mysql查看表结构命令,如下: desc 表名; show columns from 表名; describe 表名; show create table 表名;
- HDU 6280 From Tree to Graph(2018 湘潭邀请 E题,树的返祖边)
其实打返祖边就相当于$x$到祖先这一段点(不包括两端)答案都要减$1$. 然后每个点最多减$1$次$1$. #include <bits/stdc++.h> using namespace ...
- Java基于数据源的数据库访问
☞ 概述 最早接触的Java访问数据库,是通过jdbc接口.后来工作之后,一般是在服务器(如weblogic)配置数据源,通过JNDI使用数据源:最近需要在程序中动态构造数据源,查了些资料,备录于此. ...
- PIE.htc的使用
文件下载:http://css3pie.com/download/ 使用: .pie_radius{ width:200px; height:200px; background-color:red; ...
- 「LGR-049」洛谷7月月赛 D.Beautiful Pair
「LGR-049」洛谷7月月赛 D.Beautiful Pair 题目大意 : 给出长度为 \(n\) 的序列,求满足 \(i \leq j\) 且 $a_i \times a_j \leq \max ...