使用OO4O的C++包装类 查询 user_views 表的TEXT字段(类型为LONG)
通过调用oresult or = odynTV.GetFieldValue(i, (void __huge *)pCharArray, lFieldSize, &lReaded);
原型为oresult GetFieldValue(int index, void __huge *longval, long len, long *readlen) const;
发现当TEXT字段超过一定字节数后(估计2500-4000)左右就无法返回TEXT的内容了,这时readlen变量被赋值为0表示没有读出数据,其实数据是有的,查Oracle帮助文件,发现文档也示例
dyn.GetFieldValue("flong", (void *) blobbuff, 80000, &nread);
这样写也就是说80000个字节都能得到,可是我为什么超过几千个字节就获取不到了呢,2100字节左右的TEXT字段都可以获取成功。

解决方案 »

  1.   

    还是中规中矩的用OClob来读取吧。#include <oracl.h>
    #include <iostream.h>
    #include <fstream.h>// Example for OClob::Read
    int main()
    { //Initialize oo4o, connect, execute sql
    OStartup();
    ODatabase odb("ExampleDB", "scott", "tiger");
    ODynaset odyn(odb, "SELECT * FROM PART"); if (!odyn.IsOpen())
    {
    cout <<"Connect Error: "<<odb.GetErrorText()<<endl;
    cout <<"SQL Error: "<<odyn.GetErrorText()<<endl;
    return 1;
    }

    OClob oclob;
    odyn.GetFieldValue("PART_DESC", &oclob); unsigned char *buffer = 0;
    try
    {
    fstream fs;
    fs.open("descout.txt", ios::out);
    fs.setmode(filebuf::binary); unsigned long size = oclob.GetSize();

    // calculate an optimum buffersize of approximately 32k bytes
    unsigned long optchunk = oclob.GetOptimumChunkSize();
    unsigned int bufsize = ((int)(32768/optchunk)) *optchunk;
    if (bufsize > size)
    bufsize = size; buffer = (unsigned char *)malloc(bufsize); //By taking advantage of streaming we get the best performance
    //and do not need to allocate a large buffer
    oclob.EnableStreaming(size); short status= OLOB_NEED_DATA;
    unsigned long amtread=0;

    while(status == OLOB_NEED_DATA)
    {
    amtread = oclob.Read(&status, buffer, bufsize);
    fs.write(buffer, amtread);
    }

    oclob.DisableStreaming();
    fs.close();
    }
    catch(OException E)
    {
    cout<<E.GetFailedMethodName()<< " Error: "<<E.GetErrorText()<<endl;
    } if (buffer)
    free(buffer);

    return 0;
    }
      

  2.   

    不行,
    OClob oclob;
    odyn.GetFieldValue("PART_DESC", &oclob);
    LONG类型的字段不能用OClob读取,这样写将会返回OFAILURE
    文档中也是按如下定义OBlob和OClob,没有说可以用来读取LONG型字段。
    The OBlob and OClob objects provide methods for performing operations on large objects in the database of data types BLOB, CLOB, and NCLOB. In this help file BLOB, CLOB, and NCLOB datatypes are also referred to as LOB datatypes.
      

  3.   

    嗯,不错。LONG型遗留字段,确实不能使用CLOB方式读取在oo4o中。
    我试了一下,可以读取80000以上字节的LONG,使用oo4o。我试了一下,没什么问题。无论是中文字符串还是英文字符串。以下是完整的示例代码。先后插入80000字节的ASCII串和160000字节的汉字字符串。(gbk字符集)#include <oracl.h>#include <iostream>
    #include <string>int main()
    {
        OStartup();    // demo long datatype
        ODatabase odb("", "scott", "tiger");
        oresult res = odb.ExecuteSQL("drop table oo4o_long");
        if (res == OSUCCESS)
        {
            std::cout<<"drop table successfully"<<std::endl;
        }
        else
        {
            std::cout<<"table oo4o_long doesn't exist"<<std::endl;
        }    res = odb.ExecuteSQL("create table oo4o_long(id int primary key, col2 long)");
        if (res == OSUCCESS)
        {
            std::cout<<"create table successfully"<<std::endl;
        }    // Add rows
        ODynaset longdyn;
        longdyn.Open(odb, "select * from oo4o_long");
        OField id = longdyn.GetField("id");
        OField col2 = longdyn.GetField("col2");    longdyn.AddNewRecord();
        id.SetValue(1);
        std::string tmp(80000, 'a');
        col2.SetValue((const void __huge *)(tmp.c_str()), 80000);
        longdyn.Update();    longdyn.AddNewRecord();
        id.SetValue(2);
        std::string tmp2;
        for (int i=0; i<40000; i++)
        {
            tmp2.append("中国");
        }
        col2.SetValue((const void __huge *)(tmp2.c_str()), tmp2.size());
        longdyn.Update();    longdyn.Close();    longdyn.Open(odb, "select col2 from oo4o_long");
        longdyn.MoveFirst();
        std::string blobbuff;
        blobbuff.resize(90000);
        memset((void*)blobbuff.c_str(), 0, blobbuff.size());
        long nread;
        longdyn.GetFieldValue("col2", (void *) blobbuff.c_str(), blobbuff.size(), &nread);
        std::cout<<"=============the 1st row==================="<<std::endl;
        std::cout<<"read long : "<<nread<<std::endl;
        std::cout<<"the real long length " <<strlen(blobbuff.c_str())<<std::endl;    longdyn.MoveNext();
        blobbuff.resize(40000*8);
        memset((void*)blobbuff.c_str(), 0, blobbuff.size());
        longdyn.GetFieldValue("col2", (void *) blobbuff.c_str(), blobbuff.size(), &nread);
        std::cout<<"=============the 2nd row==================="<<std::endl;
        std::cout<<"read long : "<<nread<<std::endl;
        std::cout<<"the real long length " <<strlen(blobbuff.c_str())<<std::endl;
        longdyn.Close();    odb.Close();    // No need to call shutdown
        // OShutdown();
        return 0;
    }
      

  4.   

    首先诚挚地感谢iihero一直对此贴和我的关注。
    你的代码我拿来测试了,可以读取,但是我读取特定的视图还是会发生错误,看来这是某种特殊的机制。
    我的SQL是SELECT TEXT FROM USER_VIEWS。你可以对你的代码稍作修改测试一下,你会发现blobbuff对象在某几次循环会产生空字符串对象。但是如果你用SQLPLUS执行相同的动作,你会发现程序中读取不到时SQLPLUS可以读取到,这是为什么呢?
      

  5.   


    这个应该是user_views的问题。它不一定会产生实际内容。