开发者社区> 问答> 正文

发现读取的数据只是覆盖原来的数据, 原来的数据还保留,怎么在读取前清空呢?:报错

C++读取Oracle中clob类型使用otl_lob_stream,发现读取的数据只是覆盖原来的数据, 原来的数据还保留,怎么在读取前清空呢?:报错

代码如下所示:

 otl_stream s; otl_lob_stream lob; otl_long_string lstrCont(1024*1024);

    //下面是构建成Sql语句,查询id大于某个值的100行中id,url,content三列的值 CString strSql; strSql.Format( "SELECT id, url, CONTENT FROM PUBOPANALYSIS where id > %d And RowNum < 100", m_Pid);

try { s.set_lob_stream_mode(true);

   s.open(1, strSql.GetBuffer(), g_otlOra); strSql.ReleaseBuffer();

while (!s.eof()) { WebPage wp;

 ZeroMemory(chUrl, 1024*2); //这里清空获取Url的值的变量,如果这里有个清空lob的值的函数或者方法,我想问题应该可以解决

 s>>wp.nId>>chUrl>>lob; 

 wp.strUrl = chUrl;
 while (!lob.eof()) //循环获取Content的内容
 {
   lob>>lstrCont;
   strMsg.Format( "%s", lstrCont.v );
   wp.strCont += strMsg;
 }
 lob.close();

 arr.Add(wp); //这里把查询下来的数据拼成一个数组(或链表)

}

出现的情况描述如下:
 正如上述代码的SQL语句,我是想从表中获取三个字段的值分别是Id,Url和Content,其中Content是Clob类型的。
 程序执行SQL语句:“SELECT id, url, CONTENT FROM PUBOPANALYSIS where id > %d And RowNum < 100”之后可以查询出100条。

 

现在我需要循环读出查询出来的每一行数据,但是发现问题是这样的,问题出现在Content的读取上,举个例子:

  假如读取出来的第一行的Content是“1234567890”,我取出完毕;
 接着取出第二行,第二行的Content是“abcd”,比第一行短,但是读取出来的内容却是:“abcd567890”;
 之后的情况类似....

 请问各位,有什么方法解决吗?我找了很多资料没有搞懂这个怎样初始化缓冲区..用了好几次的s.flush()都没有效果。。。

展开
收起
kun坤 2020-06-07 14:03:39 841 0
1 条回答
写回答
取消 提交回答
  • Why C++######回复 @宏哥 : 好吧...可是我早已决定要解决这个问题了。######回复 @meloyi : 换语言######回复 @宏哥 : 晕....还是帮我解决一下我上面提到的问题吧。######回复 @meloyi : 是啊,, 生命没有必要被语言浪费,连接,然后查询,,那么简单的东西, 为什么要复杂了######回复 @宏哥 : 嗯 好######这种程序一般有一个属性标识数据长度的,而不是普通的以\0结尾。建议往这个方向找下API文档。你这个程序之所以能跑是因为前面的zeromemory刚好把所有数据初始化成\0了,如果你全部初始化成比如?,估计你的程序会报错。######我找了,有,但是不是我想要的,有用于算出整个数据长度,但是没有找到算当前接收的长度的方法。上面的zeromemory只是初始化了用于接收Url的变量的值,如果初始化别的值也有可能会出现我上面提到的问题,是很有可能会报错,所以清零。由于没有清空用于接收Content的方法,所以出现了上面提到的问题,如果可以找到一个方法初始化这个lob就好了,只是我一直没有找到,所以来求助。######求助啊啊啊######如果没有什么特别好的方法,就把读出来的值记录下来,然后手动清空呗,这有啥纠结的,otl本来就不是十全十美的######回复 @刘大神 : 谢谢啊。这个链接中不包含我想要的内容,链接中有提到如何读取数据记录。我上面写的代码就是这样做的。Oracle数据库中的数据是varchar类型,那么char接收是没有问题的,并且zeromemory就可以解决我上面提到的问题,而我现在想要查询的Content这个列在Oracle中是Clob类型,它不能用char接收,接收会报错,这里就是我遇到的问题。######回复 @刘大神 : 嗯 好######回复 @meloyi : 来,照着这个做,http://blog.csdn.net/heangel/article/details/7212260######回复 @刘大神 : 谢谢啊,我第一次用otl,还有很多不懂的问题,找出这个 bug都找了半天时间。之前数据库用的是sqlserver,现在改成了Oracle。不太懂otl,所以没有找到合适方法。例子也找了,但是没有找到我想要的,所以发帖求助。######回复 @meloyi : otl不是提供了N多个例子么?你看看呗,我记得没有你这么复杂啊,就是一个变量清空的过程呀,我用过mysql的那个接口,都没这么复杂######

    现在我已经把

    otl_lob_stream lob;


    的定义放在了循环体里面了,但是还是一样的效果,说明问题是在

    otl_stream s;
    这里。


    otl_stream s;
    	//otl_lob_stream lob;
    	otl_long_string lstrCont(1024*1024);
    
    	CString strSql;
    	strSql.Format( "SELECT id, url, CONTENT FROM PUBOPANALYSIS where id > %d And RowNum < 100", m_Pid);
    
    	int offline = 1;
    	try
    	{
    		s.set_lob_stream_mode(true);
    
    		s.open(1, 
    			strSql.GetBuffer(),
    			g_otlOra
    			);
    		strSql.ReleaseBuffer();
    
    		while (!s.eof())
    		{
    			WebPage wp;
    			ZeroMemory(chUrl, 1024*2);
    			otl_lob_stream lob; //放在这里
    
    			s>>wp.nId>>chUrl>>lob;
    			
    			wp.strUrl = chUrl;
    			while (!lob.eof())
    			{
    				lob>>lstrCont;
    				strMsg.Format( "%s", lstrCont.v );
    				wp.strCont += strMsg;
    			}
    			lob.close();
    
    			arr.Add(wp);
    			iRecNum++;
    		}
    	}




    ######

    感觉occi并不好用,我觉得还不如用ocilib

    http://www.oschina.net/p/ocilib

    ######嗯 谢谢######
            otl_stream s;
    	otl_lob_stream lob;
    	//otl_long_string lstrCont(1024*1024); //注释掉了这一行
    
    	CString strSql;
    	strSql.Format( "SELECT id, url, CONTENT FROM PUBOPANALYSIS where id > %d And RowNum < 200", m_Pid);
    
    	int offline = 1;
    	WirteLog( m_currPath + _T("\\Process.log"), strSql );
    	try
    	{
    		s.set_lob_stream_mode(true);
    
    		s.open(1, strSql.GetBuffer(), g_otlOra);
    		strSql.ReleaseBuffer();
    		
    		while (!s.eof())
    		{
    			WebPage wp;
    			ZeroMemory(chUrl, 1024*2);
    			s>>wp.nId>>chUrl>>lob;
    			
    			otl_long_string lstrCont(1024*1024); //最终我把这个变量声明放在了这里
    			wp.strUrl = chUrl;
    			while (!lob.eof())
    			{	
    				lob>>lstrCont;
    				strMsg.Format( "%s", lstrCont.v );
    				wp.strCont += strMsg;
    			}
    			lob.close();
    
    			arr.Add(wp);
    			iRecNum++;
    			
    			//strMsg.Format( "nId = %d, Read information succeed, content = \r\n%s", wp.nId, wp.strCont );
    			//WirteLog( m_currPath + _T("\\Process.log"), strMsg );
    		}
    	}

    如上图,我把下面的这个变量的声明换了一个位置,放在了循环里面,最后解决了我在上面提到的问题:

    otl_long_string lstrCont(1024*1024);

    虽然也可以解决问题,但是这样的话就每次读取数据都需要重新申请内存空间,效率会降低。如果能够找到初始化的方法就最好了




    ###### otl_stream s; 能弄为 while 循环内的局部变量,不就解决了吗######
     otl_stream s;
        otl_lob_stream lob; 挪到 while循环的局部变量
    ######谢谢,我把 otl_lob_stream lob; 挪到while循环里面,解决了问题######推荐你使用 C++ ORM ODB,
    2020-06-07 14:03:45
    赞同 展开评论 打赏
问答分类:
问答地址:
问答排行榜
最热
最新

相关电子书

更多
用计算和数据去改变整个世界 立即下载
低代码开发师(初级)实战教程 立即下载
阿里巴巴DevOps 最佳实践手册 立即下载