刚接触Oracle一个星期不到, 为了公司的项目勿勿学习了一下Oracle,原以为基本上搞定表空间、模式之类Sql Server用不到的概念,再学会基本的PL SQL语句就Ok了。用ADO连接Oracle的返回简单数据类型的存储过程也搞得定,心里不禁洋洋得意。我是天才,我怕谁? 上头说,电信的项目搞得定不?(电信是用Oracle)。我很豪爽地答了句:没问题!可一接到电信的存储过程就傻眼了,Package中定义了返回结果集的存储过程,而且包头给你看,包体却木有。试了很久,在csdn上问没人答。也看到一些网上的教程,不管是中文的还是外文的都木有用,这下就郁闷了。
不行,我得自己建个这样的包试试。包定义是这样的形式:
CREATE OR REPLACE PACKAGE PK_ConsolManager_LoginCheck AS
/**//******************************************************************************
NAME: PK_ConsolManager_LoginCheck
PURPOSE:
REVISIONS:
Ver Date Author Description
--------- ---------- --------------- ------------------------------------
1.0 2005-11-25 1. Created this package.
******************************************************************************/
TYPE T_CURSOR IS REF CURSOR;
PROCEDURE MyProcedure(Param1 IN NUMBER, Param3 Out Number, Param2 OUT T_CURSOR);
END PK_ConsolManager_LoginCheck ;
/
包体定义:
CREATE OR REPLACE PACKAGE BODY PK_ConsolManager_LoginCheck
AS
PROCEDURE MyProcedure(Param1 IN NUMBER,Param3 Out Number, Param2 OUT T_CURSOR)
IS
BEGIN
Open Param2 FOR
SELECT LoginName, Password from ConsoleManager where SerialRights = Param1;
Param3 := Param1;
END;
END;
/
用C# 试试ADO.net访问它,so easy,因为ADO.net有OracleTypes.Cursor类型,马上就可以得到答案!这里顺便提醒用ADO.net的兄弟们,连接字符串不易过长,要不然会有异常的 :)
再用网上的方法试试,就是把最后一个返回REF Cursor的参数省略,然后执行返回RecordSet的函数试试。
// OracleCursorApp.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <ole2.h>
#include <stdio.h>
#include "conio.h"
//Function declaration
inline void TESTHR(HRESULT x)
{if FAILED(x) _com_issue_error(x);};
void ExecuteSql(VOID);
void PrintProviderError(_ConnectionPtr pConnection);
/**////////////////////////////////////////////////////////////
// //
// Main Function //
// //
/**////////////////////////////////////////////////////////////
void main()
{
HRESULT hr = S_OK;
if(FAILED(::CoInitialize(NULL)))
return;
ExecuteSql();
//Wait here for the user to see the output.
printf("\n\n按任意键继续
");
getch();
::CoUninitialize();
}
/**////////////////////////////////////////////////////////////
// //
// ExecuteSql Function //
// //
/**////////////////////////////////////////////////////////////
VOID ExecuteSql(VOID)
{
HRESULT hr = S_OK;
// Define ADO object pointers.
// Initialize pointers on define.
// These are in the ADODB:: namespace.
_RecordsetPtr pRs = NULL;
_CommandPtr pCmd = NULL;
_ParameterPtr pPrmParam1 = NULL;
_ParameterPtr pPrmParam3 = NULL;
_ConnectionPtr pConnection = NULL;
_bstr_t strCnn("Provider=OraOLEDB.Oracle;Data Source=Console;User Id=aol;Password=123;");
_bstr_t strMessage, strAuthorID;
int intParam1;
VARIANT vtParam1;
VARIANT vtParam3;
try
{
//Open a Connection.
TESTHR(pConnection.CreateInstance(__uuidof(Connection)));
hr = pConnection->Open(strCnn,"","",adConnectUnspecified);
pConnection->CursorLocation = adUseClient;
//Open Command Object with one Parameter
TESTHR(pCmd.CreateInstance(__uuidof(Command)));
pCmd->CommandText = "PK_ConsolManager_LoginCheck.MyProcedure";
pCmd->CommandType = adCmdStoredProc;
//Get parameter value and append parameter
printf("输入: ");
scanf("%d",&intParam1);
//Define Integer/variant.
vtParam1.vt = VT_I2;
vtParam1.iVal = intParam1;
pPrmParam1 = pCmd->CreateParameter("Param1",adInteger,adParamInput,sizeof(int),vtParam1);
pCmd->Parameters->Append(pPrmParam1);
pPrmParam1->Value = vtParam1;
vtParam3.vt = VT_I2;
pPrmParam3 = pCmd->CreateParameter("Param3", adInteger, adParamOutput, sizeof(int), vtParam3);
pCmd->Parameters->Append(pPrmParam3);
//Create Recordset by executing the command
//printf("%d", pRs->GetRecordCount());
pCmd->ActiveConnection = pConnection;
pRs = pCmd->Execute(NULL,NULL,adCmdStoredProc);
_bstr_t bstrLoginName;
bstrLoginName = pRs->Fields->Item["LoginName"]->Value;
printf("登录名: %s \n", (LPCSTR) bstrLoginName);
vtParam3 = pCmd->Parameters->Item["Param3"]->Value;
printf("%d", vtParam3.intVal);
}
catch(_com_error &e)
{
_bstr_t bstrSource(e.Source());
_bstr_t bstrDescription(e.Description());
PrintProviderError(pConnection);
printf("\n 源 : %s \n 描述 : %s \n",(LPCSTR)bstrSource,(LPCSTR)bstrDescription);
}
if (pRs)
if (pRs->State == adStateOpen)
pRs->Close();
if (pConnection)
if (pConnection->State == adStateOpen)
pConnection->Close();
}
/**////////////////////////////////////////////////////////////
// //
// PrintProviderError Function //
// //
/**////////////////////////////////////////////////////////////
VOID PrintProviderError(_ConnectionPtr pConnection)
{
// Print Provider Errors from Connection object.
// pErr is a record object in the Connection's Error collection.
ErrorPtr pErr = NULL;
long nCount = 0;
long i = 0;
if( (pConnection->Errors->Count) > 0)
{
nCount = pConnection->Errors->Count;
// Collection ranges from 0 to nCount -1.
for(i = 0; i < nCount; i++)
{
pErr = pConnection->Errors->GetItem(i);
printf("Error number: %x\n Error Description: %s\n", pErr->Number,(LPCSTR) pErr->Description);
}
}
}
再试,得到异常:
输入: 0
Error number: 80040e14
Error Description: ORA-06550: 第 1 行, 第 7 列:
PLS-00306: 调用 'MYPROCEDURE' 时参数个数或类型错误
ORA-06550: 第 1 行, 第 7 列:
PL/SQL: Statement ignored
源 : OraOLEDB
描述 : ORA-06550: 第 1 行, 第 7 列:
PLS-00306: 调用 'MYPROCEDURE' 时参数个数或类型错误
ORA-06550: 第 1 行, 第 7 列:
PL/SQL: Statement ignored
按任意键继续...
网上的方法还是没用,郁闷至极啊!!!
就这样试了N次,郁闷了N天,终于有一天人品爆发,我把连接字符串改成:
_bstr_t strCnn("Provider=MSDAORA.1;Data Source=Console;User Id=aol;Password=123;");
结果得答案:
输入: 0
登录名: Jeremy
0
按任意键继续...
成功了~!
真想说句我kao!!!
这就是我用ADO操作Oracle结果集的心得。
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。