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

时间:2014-02-25 11:32:00

标签: c# oracle plsql odp.net

我们在C#程序中使用Oracle存储过程,该程序运行正常,直到我们添加了'v_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;

这是C#代码:

this.ConnectToDb();
var cmd = new OracleCommand
{
   Connection = cn,
   CommandText = "TOU.Stats_By_Date",
   CommandType = CommandType.StoredProcedure
 };
 var id = HttpContext.Current.User.Identity.Name.Split('\\')[1].ToString();
 cmd.Parameters.Add("v_SDate", OracleDbType.Varchar2).Value = 
          startdate.ToString("dd-MM-yyyy");
 cmd.Parameters.Add("v_EDate", OracleDbType.Varchar2).Value = 
          enddate.ToString("dd-MM-yyyy");
 cmd.Parameters.Add("v_user", OracleDbType.Decimal).Value = int.Parse(id);
 cmd.Parameters.Add("v_nameurn", OracleDbType.Decimal).Value = 3;
 var rc = cmd.Parameters.Add("p_cursor", OracleDbType.RefCursor);
 rc.Direction = ParameterDirection.Output;
 cmd.ExecuteNonQuery();
 this.DisconnectFromDb(); 

有什么可能出错的建议吗?两段代码中共有5个变量(4个,1个),这很好,所有数据类型似乎都匹配。我还尝试了实际v_nameurn变量的不同变体,所以我尝试了3,“3”,并事先将其定义为Int变量。

4 个答案:

答案 0 :(得分:2)

Decimal is Oracle NUMBER type ..所以更改v_user和'v_nameurn'的数据类型

cmd.Parameters.Add("v_user", OracleDbType.Decimal).Value = int.Parse(id);
cmd.Parameters.Add("v_nameurn", OracleDbType.Decimal).Value = 3;

OracleDbType Enumeration

答案 1 :(得分:2)

cmd.Parameters.Add("v_user", OracleDbType.Decimal).Value = decimal.Parse(id);
cmd.Parameters.Add("v_nameurn", OracleDbType.Decimal).Value = 3m;

处理小数时必须使用小数。对于Oracle,小数不能很好地转换为整数,反之亦然。

答案 2 :(得分:1)

这是oracle证明不是开发人员友好的RDBMS的错误之一。为什么他们不能告诉你这两个问题中的哪一个是我不知道的问题。我有一个啰嗦list of things to check归结为以下内容:

  • 缺少逗号
  • 参数数量错误
  • 参数的顺序错误,cmd.BindByName为false
  • 使用两次参数且cmd.BindByName为false(如果是内联sql)
  • 参数上的数据类型匹配。为避免出现此问题,请使用所有输入参数的.Add(“paramName”,value)重载,并推断出类型。

然而,从这个看起来,我想我要在我的列表中添加一个:确保你正在调用你认为你正在呼叫的程序。我在程序中看到了“TOU”限定符。我必须假设这是一个模式而不是基于sql脚本的包。你在改变这个模式中的proc吗?如果删除.net代码中的新参数,它是否有效或者是否会出现相同的错误?您应该得到相同的错误,但如果不这样做,您可能会将新的proc加载到错误的模式。

你可以做的最后一件事就是从一个proc的shell开始,一次添加一个proc,直到你能弄清楚发生了什么。

我会说你的int.Parse(id)有点奇怪 - 你认证的用户ID只是整数?但无论如何我都希望有一个.net错误而不是oracle错误。

答案 3 :(得分:0)

在不同的情况下,我遇到了相同的错误。

使用 OleDB 和早期版本的Oracle,您无需在调用存储过程时设置return参数:

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#/伪指令:

cn = New OleDbConnection("Provider=msdaora.1;Data Source=myTNSEntry;User ID=fakeuser;Password=abc123");
cn.Open();
oleDBCmd = cn.CreateCommand();
oleDBCmd.CommandType = CommandType.StoredProcedure;
oleDBCmd.CommandText = "ThingPackage.GetThingByID";
oleDBCmd.Parameters.Add(new OleDbParameter("thingID", "1"));

我们在没有 tSelectCursor 输入输出参数的情况下执行它:

dataReader = oleDBCmd.ExecuteReader();

按照:C# and Oracle 10g database to call stored procedure

但是,重要的是要注意,如果在Oracle 12c数据库上执行此操作,则在10g数据库上使用Oracle 9.2驱动程序时会发生错误:

  

“ ORA-06550:PLS-00306:调用'GETTHINGBYID'时参数或类型错误”

我发现如果您确实指定了期望的输出参数:

oleDBCmd.Parameters.Add(parm);

您没有获得PLS-00306:对{proc name}的调用中错误的数目或参数类型,但是添加后得到:

  

size属性的大小无效为0

这使我们几乎没有选择(我不知道如何克服这个问题)来求助于Oracle Managed Data 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 Wallet问题“网络传输:解析钱包位置时SSL失败” Oracle.ManagedDataAccess to AWS RDS DB - TCPS: Invalid SSL Wallet (Magic)