日期:2014-05-16  浏览次数:20435 次

OCI几个小问题
1、CLOG/BLOG的插入
找了很多OCI的例子以及一些PHP的例子,基本上都是同一种做法:
a、OCIStmtPrepare预处理SQL语句:"insert into mytable (myimg) values (empty_blob()) returning myimg into :pImg"
b、调用OCIDescriptorAlloc,用参数OCI_DTYPE_LOB,获得一个LOB的句柄
c、用OCIStmtBindByPos或者OCIStmtBindByName,把LOB句柄和参数:pImg绑定
d、OCIStmtExecute执行
e、OCILobWrite往LOB里面写数据
f、commit和释放资源等等

问题是这个SQL语句也太特别了,和其他数据库的SQL不一样。但是在java的实现中,并不需要这么奇怪的语法。
insert into mytable (myimg) values(?)
就足够了。
在我们的应用中,能够统一同一种SQL的写法当然是最好的,最好就是:
insert into mytable (myimg) values (:pImg) 那就和其他的数据处理一致了。

做了很多的尝试,终于找到解决的方法:
a、OCIStmtPrepare预处理SQL语句:"insert into mytable (myimg) values (:pImg)"
b、调用OCIDescriptorAlloc,用参数OCI_DTYPE_LOB,获得一个LOB的句柄
c、通过OCILobCreateTemporary函数,为LOB句柄创建临时LOB对象
d、OCILobWriteAppend往LOB句柄写数据
e、用OCIStmtBindByPos或者OCIStmtBindByName,把LOB句柄和参数:pImg绑定
f、OCIStmtExecute执行
g、commit和释放资源等等

经过简单的封装,LOB操作简单很多了:
TDBConnection conn = TDatabase::getConnection( strConnection );
TDBStatement dbStatement(conn.getStatement());
dbStatement.prepareSQL( "insert into mytable (myimg) values (:pImg)" );
dbStatement.getParam("pImg").attachInputStream( fStream );
dbStatement.execSQL();
conn.commite();

2、空字符串
插入一个空字符串,OCIBindByPos/OCIBindByName的时候,那个字符串的数据类型,不能是SQLT_LVC,用SQLT_CHR倒是没有问题。
具体为什么,只有Oracle自己知道了。

3、指定IP连接Oracle
通过OCIServerAttach里面指定绑定的SID连接数据库。用SID连接Oracle当然有它的好处。奇怪的是JDBC能用IP和Port指定连接哪个Oracle。
找遍OCI的帮助都找不到IP连接方法。google了很久,找到解决的方法,自己生成SID:
string strSID = "(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=%1)(PORT=%2)))(CONNECT_DATA=(SERVICE_NAME=%3)))";
里面的%1设为Oracle服务器的IP;%2设为Oracle服务器的Port,一般是1521;%3就是database的名字。
把这个字符串放入OCIServerAttach