C# PLS-00306:C中参数的数量或类型错误#

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 )

我们在一个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
) 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();