oracle存储过程:
...
type my_cursor is ref cursor;
...
procedure my_proc
(id in number, f3 out my_cursor,f4 out my_cursor);
is begin
open f3 for select * from sdb.test_table where age>id;
open f4 for select * from sdb.test_table2 where age>2*id;
end;
end;表test_table
id number, name varchar2, age number
链接数据库:
_RecordsetPtr m_recordset;
_ConnectionPtr m_connection;
_CommandPtr m_command;
...初始化环境...
m_connection->Open("Provider=MSDAORA.1;Use ID=sdf;Password=sdf;Data Source=oranetwork;Persist Security Info=True;");
m_command.CreateInstance(__uuidof(Command));
m_recordset.CreateInstance(__uuidof(Recordset));
m_command->ActiveConnection = m_connection;
m_command->CommandText = "{call pro_test_tabs(24)}";//存储过程
m_command->PutCommandType(adCmdText);
m_recordset = m_command->Execute(0,0,adCmdUnknown);
//取存储过程中游标的值
if (m_recordset->Fields->Count == NULL || m_recordset->Fields->Count==0)
{
std::cout << "没结果集" << std::endl;
}
else
{
int ncount = 0;
_variant_t varparam;
_bstr_t bstr;
while (!(m_recordset == NULL))
{
long colnum = m_recordset->Fields->Count;//去表格列数
if (colnum == 0) break;
std::cout << "\n--------------#table" << ++ncount << "-----------\n";
for (int j=0; j<colnum; j++)
{
varparam = m_recordset->Fields->GetItem((long)j)->Name;//获取列名
while (!m_recordset->EndOfFile)
{
for (int i=0; i<colnum; i++)
   {
varparam.Clear();
varparam = m_recordset->GetFields()->GetItem((long)i)->Value;//获取表格单元格内容
if (varparam.vt != VT_NULL)
bstr = varparam;
else
bstr = "NULL";
printf(" %s ",(const char*)bstr);;//输出表格单元格内容
   }//for
m_recordset->MoveNext();
}//while
long lngRec = 0;
m_recordset = m_recordset->NextRecordset((VARIANT *)lngRec);//获取下一个游标集合???获取不到
}while
}问题:!!!!!!
问题1:
在调用存储过程"{call pro_test_tabs(24)}"中其参数24正确传入存储过程中,即在
my_proc
(id in number, f3 out my_cursor,f4 out my_cursor);
打印出的是整个test_table表,并没有按age>id 来处理,跟踪发现获取到的id为空????????????想不通!
问题2:
取不到第二个游标f4的值,有报错:当前提供程序不支持从单一执行返回多个记录集。
该怎样取到f4游标中的值?
请高手帮忙,谢谢!

解决方案 »

  1.   

    好象很多类似你这个问题的,不知道他们解决了没有?vc里处理NULL值,是要注意的,应该写成这样DBNULL.value
      

  2.   

    你查一下test_table2里面的数据,按你的意思,里面的内容肯定有不符合要求的内容了还有这两条select 语句
    open f3 for select * from sdb.test_table where age>id; 
    open f4 for select * from sdb.test_table2 where age>2*id; 
    应该用select 具体的字段,这是写良好代码的习惯
      

  3.   

    m_connection->Open("Provider=MSDAORA.1;Use ID=sdf;Password=sdf;Data Source=oranetwork;Persist Security Info=True;"); 这个连接字符串有点问题的,在ado里面要调用out参数的ref cursor,应该还有个参数指定的。否则你调用不到out的refcursor
      

  4.   

    还要什么参数?
    为什么"{call pro_test_tabs(24)}"中的24无法传入到存储过程中去?
      

  5.   


    m_connection->Open("Provider=MSDAORA.1;Use ID=sdf;Password=sdf;Data Source=oranetwork;Persist Security Info=True;PLSQLRSet=1"); 找了一圈终于找到,这个PLSQLRSet=1是必顺设置的。你其它的代码还有没有问题,就不知道了
      

  6.   

    虽然我的问题还没解决 还是 谢谢 codearts!
      

  7.   

    等会我搞个vc test一下, 赚这100分先,呵呵
      

  8.   

    你这样调用存储过程只能接收单一查询结果,而实际上你的存储过程输出了两个记录集。
    你可以用union的方式合并两个结果集
      

  9.   


    _RecordsetPtr m_recordset; 
    _ConnectionPtr m_connection; 
    _CommandPtr m_command;  m_connection.CreateInstance(__uuidof(Connection));
    m_command.CreateInstance(__uuidof(Command)); 
    //m_recordset.CreateInstance(__uuidof(Recordset));  //...初始化环境... 
    m_connection->Open("Provider=OraOLEDB.Oracle.1;Use ID=scott;Password=dba123;Data Source=ora1;PLSQLRSet=1", "scott", "dba123", NULL); 
    m_command->ActiveConnection = m_connection; 
    m_command->CommandText = "{call my_proc(24)}";//存储过程 
    //m_command->PutCommandType(adCmdText); 
    m_recordset = m_command->Execute(0,0,adCmdUnknown); 
    //
    //取存储过程中游标的值 
    if (m_recordset->Fields->Count == NULL || m_recordset->Fields->Count==0) 

    //std::cout < < "没结果集" < < std::endl; 
    //CString str = "没有结果集";

    else 

    int ncount = 0; 
    _variant_t varparam; 
    _bstr_t bstr; 
    while (!(m_recordset == NULL)) 

    long colnum = m_recordset->Fields->Count;//去表格列数 
    if (colnum == 0) break; 
    //std::cout < < "\n--------------#table" < < ++ncount < < "-----------\n"; 
    for (int j=0; j <colnum; j++) 

    varparam = m_recordset->Fields->GetItem((long)j)->Name;//获取列名 
    while (!m_recordset->adoEOF) 

    for (int i=0; i <colnum; i++) 

    varparam.Clear(); 
    varparam = m_recordset->GetFields()->GetItem((long)i)->Value;//获取表格单元格内容 
    if (varparam.vt != VT_NULL) 
    bstr = varparam; 
    else 
    bstr = "NULL"; 
    //printf(" %s ",(const char*)bstr);;//输出表格单元格内容 
    }//for 
    m_recordset->MoveNext(); 
    }//while 
    }//for

    long lngRec = 0; 
    m_recordset = m_recordset->NextRecordset((VARIANT *)lngRec);//获取下一个游标集合???获取不到 
    }//while 

    return 0;
      

  10.   

    上面的代码,测过我的测试(在我本机),可以获取到2个集合。--这个是我的sp
    create or replace procedure my_proc
    (
    v_id number
       ,v_f3 out sys_refcursor
       ,v_f4 out sys_refcursor

    as
    begin 
    open v_f3 for select * from test_table where id>v_id;
    open v_f4 for select * from test_table2 where id>2*v_id;
    end; 
      

  11.   

    由此看来,你的问题:
        取不到第二个游标f4的值,有报错:当前提供程序不支持从单一执行返回多个记录集。 就是连接字符串里没有设置PLSQLRSet=1造成的。----------------------------------
    你的第一个问题:
        打印出的是整个test_table表,并没有按age>id 来处理,跟踪发现获取到的id为空????????????想不通!很明显了,你的表有个id字段,而你的my_proc这个sp也有个id的参数,这2个搞混了,建议你改这个参数名:v_id。否则,oracle选择id是字段名,而非参数名
      

  12.   

    codearts 你的oracle 版本是多少的啊?
    但是收到的结果是不是整个表达内容,id>v_id这个限制没有用上啊?
      

  13.   

    codearts 这个100分给你了,要是能再帮我看下id>v_id这个v_id没传进去的原因,我再开个新的100给你
      

  14.   


    用上了。
    你用sqlplus来测试下就知道了。
    sql>var x1 refcursor;
    sql>var x2 refcursor;
    sql>begin my_proc(24, :x1, :x2);
    sql>print :x1;
    sql>print :x2;你在sqlplus下依次执行以上的命令,看看结果就知道了。
      

  15.   

    你的代码,最前面的那个for的逻辑有点错误,应该是: int ncount = 0; 
    _variant_t varparam; 
    _bstr_t bstr; 
    while (!(m_recordset == NULL)) 

    long colnum = m_recordset->Fields->Count;//去表格列数 
    if (colnum == 0) break; 
    //std::cout < < "\n--------------#table" < < ++ncount < < "-----------\n"; 
    for (int j=0; j <colnum; j++) 

    varparam = m_recordset->Fields->GetItem((long)j)->Name;//获取列名 
    //输出列名
    }//for ------- 这个 for 应该在这里结果 while (!m_recordset->adoEOF) 

    for (int i=0; i <colnum; i++) 

    varparam.Clear(); 
    varparam = m_recordset->GetFields()->GetItem((long)i)->Value;//获取表格单元格内容 
    if (varparam.vt != VT_NULL) 
    bstr = varparam; 
    else 
    bstr = "NULL"; 
    //printf(" %s ",(const char*)bstr);;//输出表格单元格内容 
    }//for 
    m_recordset->MoveNext(); 
    }//while 

    long lngRec = 0; 
    m_recordset = m_recordset->NextRecordset((VARIANT *)lngRec);//获取下一个游标集合???获取不到 
    }//while