ado vc调oracle 存储过程问题?求救!!

anran2008 2008-12-08 03:39:16
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游标中的值?
请高手帮忙,谢谢!


...全文
132 16 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
16 条回复
切换为时间正序
请发表友善的回复…
发表回复
zhangyong369 2008-12-08
  • 打赏
  • 举报
回复
[Quote=引用 14 楼 codearts 的回复:]
引用 12 楼 anran2008 的回复:
codearts 你的oracle 版本是多少的啊?
但是收到的结果是不是整个表达内容,id>v_id这个限制没有用上啊?


用上了。
你用sqlplus来测试下就知道了。
sql>var x1 refcursor;
sql>var x2 refcursor;
sql>begin my_proc(24, :x1, :x2);
sql>print :x1;
sql>print :x2;

你在sqlplus下依次执行以上的命令,看看结果就知道了。
[/Quote]可以
codearts 2008-12-08
  • 打赏
  • 举报
回复
你的代码,最前面的那个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
codearts 2008-12-08
  • 打赏
  • 举报
回复
[Quote=引用 12 楼 anran2008 的回复:]
codearts 你的oracle 版本是多少的啊?
但是收到的结果是不是整个表达内容,id>v_id这个限制没有用上啊?
[/Quote]

用上了。
你用sqlplus来测试下就知道了。
sql>var x1 refcursor;
sql>var x2 refcursor;
sql>begin my_proc(24, :x1, :x2);
sql>print :x1;
sql>print :x2;

你在sqlplus下依次执行以上的命令,看看结果就知道了。
anran2008 2008-12-08
  • 打赏
  • 举报
回复
codearts 这个100分给你了,要是能再帮我看下id>v_id这个v_id没传进去的原因,我再开个新的100给你
anran2008 2008-12-08
  • 打赏
  • 举报
回复
codearts 你的oracle 版本是多少的啊?
但是收到的结果是不是整个表达内容,id>v_id这个限制没有用上啊?
codearts 2008-12-08
  • 打赏
  • 举报
回复
由此看来,你的问题:
取不到第二个游标f4的值,有报错:当前提供程序不支持从单一执行返回多个记录集。

就是连接字符串里没有设置PLSQLRSet=1造成的。

----------------------------------
你的第一个问题:
打印出的是整个test_table表,并没有按age>id 来处理,跟踪发现获取到的id为空????????????想不通!

很明显了,你的表有个id字段,而你的my_proc这个sp也有个id的参数,这2个搞混了,建议你改这个参数名:v_id。否则,oracle选择id是字段名,而非参数名
codearts 2008-12-08
  • 打赏
  • 举报
回复
上面的代码,测过我的测试(在我本机),可以获取到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;
codearts 2008-12-08
  • 打赏
  • 举报
回复

_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;
xcluii 2008-12-08
  • 打赏
  • 举报
回复
你这样调用存储过程只能接收单一查询结果,而实际上你的存储过程输出了两个记录集。
你可以用union的方式合并两个结果集
codearts 2008-12-08
  • 打赏
  • 举报
回复
等会我搞个vc test一下, 赚这100分先,呵呵
anran2008 2008-12-08
  • 打赏
  • 举报
回复
虽然我的问题还没解决 还是 谢谢 codearts!
codearts 2008-12-08
  • 打赏
  • 举报
回复

m_connection->Open("Provider=MSDAORA.1;Use ID=sdf;Password=sdf;Data Source=oranetwork;Persist Security Info=True;PLSQLRSet=1");

找了一圈终于找到,这个PLSQLRSet=1是必顺设置的。

你其它的代码还有没有问题,就不知道了
anran2008 2008-12-08
  • 打赏
  • 举报
回复
还要什么参数?
为什么"{call pro_test_tabs(24)}"中的24无法传入到存储过程中去?
codearts 2008-12-08
  • 打赏
  • 举报
回复
m_connection->Open("Provider=MSDAORA.1;Use ID=sdf;Password=sdf;Data Source=oranetwork;Persist Security Info=True;");

这个连接字符串有点问题的,在ado里面要调用out参数的ref cursor,应该还有个参数指定的。否则你调用不到out的refcursor
Andy__Huang 2008-12-08
  • 打赏
  • 举报
回复
你查一下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 具体的字段,这是写良好代码的习惯
sleepzzzzz 2008-12-08
  • 打赏
  • 举报
回复
好象很多类似你这个问题的,不知道他们解决了没有?

vc里处理NULL值,是要注意的,应该写成这样DBNULL.value

17,140

社区成员

发帖
与我相关
我的任务
社区描述
Oracle开发相关技术讨论
社区管理员
  • 开发
  • Lucifer三思而后行
  • 卖水果的net
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧