C# PLS-00306:C中参数的数量或类型错误#
我们在一个C#程序中使用了一个Oracle存储过程,在添加“v#u nameurn”变量之前,该过程一直运行良好 以下是Oracle的过程:C# PLS-00306:C中参数的数量或类型错误#,c#,oracle,plsql,odp.net,C#,Oracle,Plsql,Odp.net,我们在一个C#程序中使用了一个Oracle存储过程,在添加“v#u nameurn”变量之前,该过程一直运行良好 以下是Oracle的过程: create or replace procedure stats_By_Date ( v_SDate IN varchar2, v_EDate IN varchar2, v_user IN number, v_nameurn IN number, p_cursor OUT SYS_REFCURSOR )
create or replace procedure stats_By_Date (
v_SDate IN varchar2,
v_EDate IN varchar2,
v_user IN number,
v_nameurn IN number,
p_cursor OUT SYS_REFCURSOR
) as
BEGIN
OPEN p_cursor FOR
select T1.Staff_No,
T3.Title,
T2.Verno,
To_char(T1.Response_dt, 'DD/MM/YYYY'),
T5.Response,
T6.Forenames||' '||T6.Surname
from TOU.Users_version_link T1,
TOU.Version T2,
TOU.name T3,
TOU.Admin_Access T4,
Tou.CV_Response T5,
corp.wforce_employee@remote_DWLive T6
where T1.Version_urn=T2.Urn
and T1.Name_urn= T3.urn
and T3.urn = T4.name_urn
and T1.Response_urn=T5.urn
and T1.staff_no=T6.Staff_Number
and Trunc(T1.Response_dt) >= To_date(v_Sdate, 'DD/MM/YYYY')
and Trunc(T1.Response_dt) <= To_date(v_EDate, 'DD/MM/YYYY')
and T4.Staff_No = v_user
and T3.urn = v_nameurn;
End;
PROCEDURE getThingByID
(thingID NUMBER,
results IN OUT tSelectCursor) IS
selectCursor tSelectCursor;
BEGIN
OPEN selectCursor FOR
SELECT Name, Description, IsDeleted
FROM thing WHERE thingID = getThingByID.thingID;
results := selectCursor;
END;
关于可能出现的问题有什么建议吗?两段代码中总共有5个变量(4进1出),这很好,所有数据类型似乎都匹配。我还尝试了实际
v_nameurn
变量的不同变体,因此我尝试了3,“3”,并预先将其定义为Int变量。十进制是Oracle数字类型。。因此,请更改v_user
和“v_nameurn”的数据类型
cmd.Parameters.Add("v_user", OracleDbType.Decimal).Value = int.Parse(id);
cmd.Parameters.Add("v_nameurn", OracleDbType.Decimal).Value = 3;
处理小数时必须使用小数。对于Oracle来说,小数不能很好地转换为整数,反之亦然 这是oracle被证明不是开发人员友好型RDBMS的错误之一。为什么他们不能告诉你这两个问题中的哪一个是我不知道的问题。我的长篇大论可以归结为以下几点:
- 缺少逗号
- 参数数目错误
- 参数顺序错误,cmd.BindByName为false
- 使用参数两次,cmd.BindByName为false(如果是内联sql)
- 参数上的数据类型匹配。为避免此问题,请对所有输入参数使用.Add(“paramName”,value)重载,并让类型被推断
然而,从外观上看,我想我将在列表中再添加一个:确保您正在调用您认为正在调用的过程。我在程序上看到了“TOU”限定符。我必须假设这是一个模式,而不是一个基于sql脚本的包。您正在更改此架构中的进程吗?如果删除.net代码中的新参数,它会起作用还是会出现相同的错误?您应该会收到相同的错误,但如果没有,则可能将新进程加载到错误的模式
你能做的最后一件事就是从一个proc的外壳开始,然后一次添加一个proc,直到你知道发生了什么
我会说你的int.Parse(id)有点奇怪-你的经过身份验证的用户id只是int吗?但是在任何情况下,我都希望出现.net错误,而不是oracle错误。我在不同的情况下遇到了相同的错误
使用OleDB和Oracle的早期版本,调用存储过程时不设置返回参数:
create or replace procedure stats_By_Date (
v_SDate IN varchar2,
v_EDate IN varchar2,
v_user IN number,
v_nameurn IN number,
p_cursor OUT SYS_REFCURSOR
) as
BEGIN
OPEN p_cursor FOR
select T1.Staff_No,
T3.Title,
T2.Verno,
To_char(T1.Response_dt, 'DD/MM/YYYY'),
T5.Response,
T6.Forenames||' '||T6.Surname
from TOU.Users_version_link T1,
TOU.Version T2,
TOU.name T3,
TOU.Admin_Access T4,
Tou.CV_Response T5,
corp.wforce_employee@remote_DWLive T6
where T1.Version_urn=T2.Urn
and T1.Name_urn= T3.urn
and T3.urn = T4.name_urn
and T1.Response_urn=T5.urn
and T1.staff_no=T6.Staff_Number
and Trunc(T1.Response_dt) >= To_date(v_Sdate, 'DD/MM/YYYY')
and Trunc(T1.Response_dt) <= To_date(v_EDate, 'DD/MM/YYYY')
and T4.Staff_No = v_user
and T3.urn = v_nameurn;
End;
PROCEDURE getThingByID
(thingID NUMBER,
results IN OUT tSelectCursor) IS
selectCursor tSelectCursor;
BEGIN
OPEN selectCursor FOR
SELECT Name, Description, IsDeleted
FROM thing WHERE thingID = getThingByID.thingID;
results := selectCursor;
END;
C#/psuedo:
我们在不使用tSelectCursor输入输出参数的情况下执行它:
dataReader = oleDBCmd.ExecuteReader();
根据:
但是,需要注意的是,在10g数据库上使用Oracle 9.2驱动程序时,如果使用Oracle 12c数据库执行此操作,则会出现以下错误:
“ORA-06550:PLS-00306:调用'GETTHINGBYID'时参数的数目或类型错误”
我发现,如果您确实指定了预期的输出参数:
oleDBCmd.Parameters.Add(parm);
在调用{proc name}错误时,您不会得到PLS-00306:错误的参数数量或类型,但添加后您会得到:
size属性的大小0无效
这使得我们几乎没有选择(我不知道如何克服这一点)求助于Oracle托管数据ODP.Net驱动程序
使用ODP.Net调用存储过程时,必须设置返回参数,与OleDB不同,Oracle驱动程序提供REFCURSOR输出参数:
PROCEDURE getThingByID2
(thingID NUMBER,
results OUT SYS_REFCURSOR) IS
BEGIN
OPEN refCursor FOR
SELECT Name, Description, IsDeleted
FROM thing WHERE thingID = getThingByID2.thingID;
END;
现在我们可以很容易地称之为:
ocn = New OracleConnection("Data Source=myTNSEntry;User ID=fakeuser;Password=abc123");
ocn.Open();
ocmd = ocn.CreateCommand();
ocmd.CommandType = CommandType.StoredProcedure();
ocmd.CommandText = "ThingPackage.GetThingByID2";
ocmd.Parameters.Add(New OracleParameter("thingID", "1"));
ocmd.Parameters.Add(New OracleParameter("results", OracleDbType.RefCursor, ParameterDirection.InputOutput));
dataReader = ocmd.ExecuteReader();
使用SSL时,您可能会遇到.Net Oracle SSL钱包问题“网络传输:解析钱包位置时SSL失败”:
如果这是一个愚蠢的问题,很抱歉,但是你每次都要关闭连接吗?谢谢,是的,我已经更新了我的代码。我不知道你为什么要从C#中以“dd-MM-yyyy”
格式传递日期,并在Oracle中使用“dd/MM/yyyy”
格式将其转换为日期。虽然这可能不是错误的原因,但对我来说似乎是错误的。您也可以尝试将3解析为整数,就像您对id
所做的那样,我的意思是int.Parse(3)
,我不知道它在C中是如何工作的,但值得一试。如果这是另一个愚蠢的问题,那么很抱歉,但是您确定您在模式中创建了新版本的存储过程(使用v\u nameun
参数)(TOU
)C#code在哪里查找它?检查的一种方法是查看SQL*Plus中的description TOU.STATS_BY_DATE
命令是否显示新参数。另一个小建议是,确保为OracleCommand将BindByName
属性设置为True
,否则Oracle会尝试匹配位置参数y、 这可能不会影响您的错误,但这是一个很好的做法。非常感谢,我已经更新了我的代码(和原始帖子),但不幸的是仍然会出现相同的错误。
ocn = New OracleConnection("Data Source=myTNSEntry;User ID=fakeuser;Password=abc123");
ocn.Open();
ocmd = ocn.CreateCommand();
ocmd.CommandType = CommandType.StoredProcedure();
ocmd.CommandText = "ThingPackage.GetThingByID2";
ocmd.Parameters.Add(New OracleParameter("thingID", "1"));
ocmd.Parameters.Add(New OracleParameter("results", OracleDbType.RefCursor, ParameterDirection.InputOutput));
dataReader = ocmd.ExecuteReader();