原文地址:http://otl.sourceforge.net/otl3_faq.htm
请将疑问及评论发送至:skuchin@gmail.com
问 OTL: OTL是如何处理NULL的?
- 调用 otl_stream::is_null()检查从数据流(stream)中读取的是否为空值.
- 利用模板类 otl_value<T>.
- 如果有必要将读出来为空的变量值设置为某一值(对于输出值为NULL,OTL在默认情况下对输出缓冲区不作任何操作的)下面的宏可以做到:
- OTL_DEFAULT_NUMERIC_NULL_TO_VAL
- OTL_DEFAULT_DATETIME_NULL_TO_VAL
- OTL_DEFAULT_STRING_NULL_TO_VAL
- OTL_DEFAULT_CHAR_NULL_TO_VAL
- OTL_USER_DEFINED_STRING_CLASS_DEFAULT_NULL_TO_VAL
问 OTL: 为什么OTL不支持T-SQL存储过程中的INSERT,UPDATE,DELETE指令?
T-SQL存储过程中的INSERT/UPDATE/DELETE指令返回所处理过的行数(RPC),当使用这种OTL/C++代码时,这些行数(RPCs)作为独立的结果集通过微软的MS SQL Native Client(SNAC)返回给调用者.OTL不会处理这些RPC的结果集,因此使用者在存储过程中需要用"SET NOCOUNT ON"指令来关闭这个功能(即不让返回这些结果集--译著),例如:
CREATE PROCEDURE my_proc
...
AS
SET NOCOUNT ON
...问 OTL:如何插入或更新类型为NVARCHAR/NCHAR且数量超过2000的字段的值?
所有版本的MS SQL ODBC/Natie Client(包括MS SQL 2008)都有一个数量的限制:对于OTL的类型变量:v<char[XXX]>,如果定义了#define OTL_UNICODE并且将这个变量与一个类型为NVARCHAR/NCHAR的字段绑定,这个数量只限于2000个UTF-16类型的字符.也就是说如果定义变量为:<char[2002]>,MS SQL 2005将会曝出如下的错误提示:
[Microsoft][SQL Native Client]Invalid precision value
同样情形,MS SQL 2008的错误信息则更加详细:
[Microsoft][SQL Server Native Client 10.0][SQL Server]The size (XXX) given to the parameter '@PN' exceeds the maximum allowed (4000).
在MSDN的网站上我还没找到任何对这个错位消息的解释,如果谁找到了相关的网页,请告我,我会将这个URL附在本答案后面.
如果有需要去insert / update 类型为NVACHAR / NCHAR且数量超过2000的字段,可以用:v<varchar_long>来代替 :v<char[XXX]>.可以将otl_long_unicode_string和:v<varchar_long>配合使用,例如:
......
create table test_tab(f1 int, f2 nvarchar(4000));
......
db.set_max_long_size(4000); // set the maximum varchar long to 4000 characters
otl_stream o(3, // buffer size should can be > 1
"insert into test_tab values(:f1<int>,:f2<varchar_long>)",
db // connect object
);
otl_long_unicode_string f2(4000);
for(int i=1;i<=5;++i){
o<<i;
for(int j=0;j<4000;++j)
f2[j]=...;
f2.set_len(4000);
o<<f2;
}
除了otl_long_unicode_string, std::wstring也可以配合varchar_long使用,类似的例子 368.问 OTL:MS SQL Server为什么不支持带绑定变量的嵌套查询?
在你打开嵌套查询的数据流时,尝试在otl_connect参数后面加参数otl_implicit_select:
otl_stream s(1,
"select dt from "
" (select "
" dateadd(day, :v<int>, getdate() "
" )dt ) xt ",
db, // connect object
otl_implicit_select
);问题就出现了:函数SQLPrepare() 没有返回任何查询输出列的指示器(抛出一个OTL异常:Column: 0<UNKNOWN>),看起来就像嵌套查询指令被转换为一个临时的存储过程,也就是说你必须指明它是一个存储过程,并且显式的返回一个结果集。我不知道数据库系统为什么这么做,可能是一种性能优化技术。
问 OTL:当我再MySQL中的某个表中插入一个新的记录时,我却查询不到他,出什么问题了?
当你在一个otl_stream中使用预设置好的SELECT指令,并且持续重复执行这个指令来得到新记录时,每次数据序列取出完毕后你都必须进行提交操作(调用otl_connect::commit()).这个提交操作让你的MySQL服务器知道你当前的只读事务已经执行完毕,服务器就可以开始一个新的事务了,这样最近插入数据库的那条记录才能通过SELECT指令展现出来.换句话说,你需要提交你的SELECT指令才能看到新插入的记录.
问:我们如何才能不通过ODBC数据源而直接访问数据库?
请参考网站。
问:OTL是线程安全的吗?
OTL没有使用任何互斥锁和零临区。如果每一个线程都拥有自己的otl_connect 对象,那么就没有必要使用互斥锁。如果在多个线程中共享数据库的连接,那么对OTL调用进行同步控制就是开发者的责任了。通常,数据库的APIs是不保证线程安全的。otl_connect::otl_initialize 传递一个标志位到数据库API,仅仅是为了让API知道程序再多线程模式上运行的。
问:OTL:OTL能在SQLite上运行吗?
是的,OTL/ODBC 能在SQLite上运行,详情请看考下面的例子。
问:OTL:支持Oracle 10g或者11g吗?
是的,使用宏 #define OTL_ORA10G, OTL_ORA10G_R2, 或者OTL_ORA11G。
问:OTL:支持 SAP DB吗?
是的,OTL/ODBC能在SAP DB上运行,更多的详情,请参考SAP DB的 例子。
问:OTL:支持PL/SQL中的CLOBs/BLOBs吗?
答案是:依据具体的情况而定.你需要时刻牢记要把CLOB/BLOB看成PL/SQL的一个数据类型:一个大对象的定位器,而不是一个值.这就是说,这个对象本身首要要被创建,这个定位器需要从数据库中得到并传递给C++,只有这样这个定位器才能传到PL/SQL.也可以参考代码示例 378.
问:OTL:支持Unicode吗?
是的,详情请看考OTL示例和参考手册。
问:OTL:支持Oracle 9i吗?
是的,从4.0.0版本开始,OTl引进了宏#define OTL_ORA9I,这就意味着它支持Oracle 9i。OTL 4.0.0本身就不再是OTL_ORA8I的同义词,但是在随后的发行版本里,当OTL开始使用OCI9独有的特性时,就必须使用宏OTL_ORA9I。详情请参考"what's new in OTL 4"。
问:OTL:支持Interbase 6.x吗?
是的,从4.0.0版本开始,OTl就支持Interbase开源的ODBC驱动。详情请参考"what's new in OTL 4"。问:OTL:支持PostgreSQL 7.x / 8.x吗?
是的,从4.0.0版本开始,OTL通过ODBC支持PostgreSQL 7.x / 8.x。详情请参考"what's new in OTL 4"。问:OTL:支持DB2, Call Level Interface (CLI)?吗?
是的,从3.2.7版本开始,OTl新加入了一味香料:OTL/DB2-CLI. OTL/DB2-CLI使用DB2的原生数据库API:Call Level Interface。OTL/DB2-CLI 99.5%的兼容于ODBC 3.x的规范及其其扩展。OTL头文件中就包含CLI原生的头文件,并且可以在Windows或者是Unix(主要是AIX)平台上使用DB2-CLI的原生对象库。问:OTL/ODBC: 支持MyODBC/MySQL吗?
是的, 从3.2.4版本开始,OTL/ODBC就兼容MyODBC。获取更多MyODBC相关细节请参考MyODBC for MySQL.。宏定义#define OTL_ODBC_MYSQL 应该和MySQL默认的字段类型结合使用,因为在这种情形下OTL关闭了ODBC函数调用的事务性。如果想在MyODBC3.5中使用了InnoDB字段类型,就应该使用宏定义#define OTL_ODBC。问:OTL/OCI8能和XA-connectivity一起工作吗?
是的,当一个XA类型的连接建立后,为了获得与OCI8相兼容的环境和上下文服务句柄,xaoEnv()和xaoSvcCtx()函数就应该被调用。此后otl_connect::rlogon() 才能利用这个句柄来创建一个OTL连接。rlogon()与Pro*C 8.x相结合使用的用法类似。如何使用 rlogon() 这种类型的函数,详情请看例子59。问:支持C++ string(std::string)吗?如何再OTL中整合Standard Template Library (STL)?
OTL3.2.0以及更高的版本支持std::string(请看例子72, 73, 74),当然OTL也支持遵从STL的流迭代器otl_input_iterator, otl_output_iterator。问:在任何情况下,OTL支持哪些主流的C++编译器?
- Sun C++ Workshop 6.x and higher
- GNU C++ 3.3.x and higher
- VC++ 6.0 and higher
- HP ANSI C++ (aCC) 1.x
- AIX, Visual Age C++ 6.x and higher
- Borland C++ 5.x
- Intel C++ 7.0, 8.0, 9.x (Windows, Linux)
为了完善这些列表,如果你所使用的编译器不再上述列表中,欢迎将你的C++编译器名称发邮件给我。
问:有什么方法可以读/写大的BLOB而不用在内存中分配大的缓冲区?
OTL3.1.4为Oracle 8 CLOBs/BLOBs支持stream mode,更多详情请看例子56, 57。问:有什么方法可以调用将PL/SQL表作为参数的存储过程?
OTL3.1通过 otl_streams 和 special template data containers支持PL/SQL表,更多详情请看例子 49, 50, 51, 52。问:你将会继续通过邮件传递你的代码,或者有意将你的代码存放在你的网站上?
从现在开始,OTL头文件可以用下载的方式获得。问:就我们所关心的值为NULL的问题,Large Objects (LOBs)和其他类型在行为方面有什么不同?
详情请参考 "Large Objects and NULLs" 。
问:怎样从 otl_stream中读取/写入时间日期信息?
答案是利用otl_datetime数据容器,它是在OTL 3.1.26中引进的,详情参考示例38, 39, 40。最基本的:Oracle DATE或者是MS SQL Server DATETIME能用otl_datetime类型的变量来读/写。
问:在SQL指令执行完成后,我们如何获得处理的行数?
函数 direct_exec() 返回一个long int值,当这个值>=0时,即为SQL指令所连续处理的行数,同样otl_stream::get_rpc() 也返回一个long int值,用来指示处理过的行数。处理计数只在INSERT, UPDATE,和DELETE指令中定义.SELECT指令的RPC(row processed counts)就是获取的行数.对于其他SQL指令,PL/SQL块,存储过程调用,这个计数总是0 。