【问题标题】:Oracle Procedure - PLS-00306: wrong number or types of argumentsOracle 过程 - PLS-00306:错误的参数数量或类型
【发布时间】:2017-02-25 10:49:47
【问题描述】:

我的程序在执行时出现以下错误:

Error starting at line : 1 in command -
exec p_matrika(2010,2.5,'26311330')
Error report -
ORA-06550: line 1, column 7:
PLS-00306: wrong number or types of arguments in call to 'P_MATRIKA'
ORA-06550: line 1, column 7:
PL/SQL: Statement ignored
06550. 00000 -  "line %s, column %s:\n%s"
*Cause:    Usually a PL/SQL compilation error.
*Action:

程序编译没有错误。我还检查了 SQL 语句,它按原样工作,返回 1 行,所以一定是我在程序本身做错了什么。对于 SQL 语句的格式有点混乱,我深表歉意。当我复制和粘贴它时,它不知何故搞砸了。

create or replace PROCEDURE P_MATRIKA 
(
    leto IN NUMBER, 
    rating IN NUMBER,
    davcna IN VARCHAR2,
    unsec_out OUT NUMBER,
    supp_out OUT NUMBER,
    sec_out OUT NUMBER,
    unsec_limit OUT NUMBER,
    supp_limit OUT NUMBER,
    sec_limit OUT NUMBER,
    unsec_tenor OUT NUMBER,
    supp_tenor OUT NUMBER,
    sec_tenor OUT NUMBER
)
AS
    out_unsec NUMBER;
    out_supp NUMBER;
    out_sec NUMBER;
    limit_unsec NUMBER;
    limit_supp NUMBER;
    limit_sec NUMBER;
    tenor_unsec NUMBER;
    tenor_supp NUMBER;
    tenor_sec NUMBER;       
BEGIN
    with 
        matrika_osnova 
    as
    (
    select distinct a.par_davcna, nvl(a.unsecured,0) unsec_out,
                 nvl(a.supported,0) supp_out, nvl(a.secured,0) sec_out,
                 x.tip_sub, x.cispri, x.kraban, x.dolfinobv,
                 y.ltv_tip, y.rating, y.unsec_pct, q.supp_pct,
                 w.sec_pct, p.unsec_maxznes, s.sec_maxznes,
                 case when y.unsec_pct * nvl(x.cispri,0) > nvl(p.unsec_maxznes,0) then
                                     nvl(p.unsec_maxznes,0) - nvl(x.kraban,0) + (nvl(x.dolfinobv,0)/5)
                            else
                                    case when y.unsec_pct * nvl(x.cispri,0) - 
                                                        nvl(x.kraban,0) + (nvl(x.dolfinobv,0)/5) < 0 then
                                                        0
                                            else
                                                        y.unsec_pct * nvl(x.cispri,0) - nvl(x.kraban,0) + 
                                                        (nvl(x.dolfinobv,0)/5)
                                    end
                 end unsec_max,
                 case when q.supp_pct * nvl(x.cispri,0) > nvl(s.sec_maxznes,0) then
                                     nvl(s.sec_maxznes,0) - nvl(x.kraban,0) + (nvl(x.dolfinobv,0)/5)
                            else
                                    case when q.supp_pct * nvl(x.cispri,0) - nvl(x.kraban,0) + 
                                                        (nvl(x.dolfinobv,0)/5) < 0 then
                                                        0
                                            else
                                                        q.supp_pct * nvl(x.cispri,0) - nvl(x.kraban,0) + 
                                                        (nvl(x.dolfinobv,0)/5)
                                    end
                 end supp_max,
                 case when w.sec_pct * nvl(x.cispri,0) > nvl(s.sec_maxznes,0) then
                                     nvl(s.sec_maxznes,0) - nvl(x.kraban,0) + (nvl(x.dolfinobv,0)/5)
                            else
                                    case when w.sec_pct * nvl(x.cispri,0) - nvl(x.kraban,0) + 
                                                        (nvl(x.dolfinobv,0)/5) < 0 then
                                                        0
                                            else
                                                        w.sec_pct * nvl(x.cispri,0) - nvl(x.kraban,0) + 
                                                        (nvl(x.dolfinobv,0)/5)
                                    end
                 end sec_max,
                 d.unsec_tenor, e.supp_tenor, f.sec_tenor                               
    from sco_matrika_banka a
    inner join
                        (select b.tip_sub, b.par_davcna, b.cispri, b.kraban, b.dolfinobv
                         from scoring_gvin b
                         where b.leto = leto) x --IN parameter
    on a.par_davcna = x.par_davcna
    inner join 
                        (select a.tip_sub, a.ltv_tip, 
                         a.max_znesek unsec_maxznes
                         from sco_sif_ltv_maxznes a
                         where a.ltv_tip = 1) p
    on x.tip_sub = p.tip_sub
    inner join 
                        (select a.tip_sub, a.ltv_tip, 
                         a.max_znesek sec_maxznes
                         from sco_sif_ltv_maxznes a
                         where a.ltv_tip = 3) s
    on x.tip_sub = s.tip_sub
    inner join
                        (select a.tip_sub, a.ltv_tip, 
                                        a.rating, a.ltv_pct unsec_pct
                         from sco_sif_ltv_pct a
                         where a.ltv_tip = 1
                         and a.rating = rating) y --IN parameter
    on x.tip_sub = y.tip_sub
    inner join
                        (select a.tip_sub, a.ltv_tip, 
                                        a.rating, a.ltv_pct supp_pct
                         from sco_sif_ltv_pct a
                         where a.ltv_tip = 2
                         and a.rating = rating) q --IN parameter
    on x.tip_sub = y.tip_sub
    inner join
                        (select a.tip_sub, a.ltv_tip, 
                                        a.rating, a.ltv_pct sec_pct
                         from sco_sif_ltv_pct a
                         where a.ltv_tip = 3
                         and a.rating = rating) w --IN parameter
    on x.tip_sub = y.tip_sub
    inner join
                         (select a.tip_sub, a.tenor unsec_tenor
                            from sco_sif_ltv_tenor a
                            where a.ltv_tip = 1) d
    on x.tip_sub = d.tip_sub
    inner join
                         (select a.tip_sub, a.tenor supp_tenor
                            from sco_sif_ltv_tenor a
                            where a.ltv_tip = 2) e
    on x.tip_sub = e.tip_sub
    inner join
                         (select a.tip_sub, a.tenor sec_tenor
                            from sco_sif_ltv_tenor a
                            where a.ltv_tip = 3) f
    on x.tip_sub = f.tip_sub
    where a.par_davcna = davcna) --IN parameter

    select a.unsec_out, a.supp_out, a.sec_out,
                 case when a.unsec_max - a.unsec_out < 0 then
                                     0
                            else
                                     a.unsec_max - a.unsec_out
                 end unsec_limit,
                             case when a.supp_max - a.supp_out < 0 then
                                     0
                            else
                                     a.supp_max - a.supp_out
                 end supp_limit,
                             case when a.sec_max - a.sec_out < 0 then
                                     0
                            else
                                     a.sec_max - a.sec_out
                 end sec_limit,
                 a.unsec_tenor, a.supp_tenor, a.sec_tenor
                 into
                 out_unsec, out_supp, out_sec, limit_unsec, limit_supp,
                 limit_sec, tenor_unsec, tenor_supp, tenor_sec
    from matrika_osnova a;

    unsec_out := out_unsec;
    supp_out := out_supp;
    sec_out := out_sec;
    unsec_limit := limit_unsec;
    supp_limit := limit_supp;
    sec_limit := limit_sec;
    unsec_tenor := tenor_unsec;
    supp_tenor := tenor_supp;
    sec_tenor := tenor_sec;             
END P_MATRIKA;

【问题讨论】:

  • 您的过程有 12 个参数,而您只传递了 3 个。您希望 OUT 值去哪里?
  • @AlexPoole 感谢您的快速回复。我对 PL/SQL 很陌生。我的目标是获得指定 9 个 OUT 参数的行。
  • 您的过程有多个标量输出参数,您根本不会得到“行”。您打算如何处理通话结果;你将如何使用这些值?您的过程中的查询实际上会返回多少行——总是正好是一个? (不知道你为什么在这里使用一个过程,而不是直接运行查询。)
  • 它假设将值返回到我的 C# 应用程序。是的,总是正好 1 行。我可以使用内联 SQL,但这样每次运行时 SQL 都必须编译,而存储过程只编译一次。
  • 这是不正确的。如果不在缓存中,则对 SQL 进行硬解析,如果在缓存中,则进行更快的软解析。该过程的 PL/SQL 编译一次,它调用的 SQL 被视为直接调用,并且仍将获得软解析。不过,出于其他原因(例如可维护性等),您可能仍希望在程序中使用它。

标签: oracle stored-procedures


【解决方案1】:

您的调用中的参数数量必须与过程规范中的形式参数数量相同(除非有任何默认的 IN 参数,这里不是这种情况)。每个 OUT 参数都必须有一个来自调用者的对应变量,以便将值放入。您的过程有 12 个形式参数。目前您正在为三个 IN 参数提供值,但您没有提供变量来接受九个 OUT 参数。

您可以使用在与您的调用相同的匿名块中声明的本地 PL/SQL 变量,或者 - 可能更有用且更接近您的 C# 调用 - 在 SQL*Plus 或 SQL Developer 中绑定变量(基于您对 @ 的使用) 987654322@) 你可以用variable 命令定义:

variable out_unsec NUMBER;
variable out_supp NUMBER;
variable out_sec NUMBER;
variable limit_unsec NUMBER;
variable limit_supp NUMBER;
variable limit_sec NUMBER;
variable tenor_unsec NUMBER;
variable tenor_supp NUMBER;
variable tenor_sec NUMBER;     

exec p_matrika(2010, 2.5, '26311330', :out_unsec, :out_supp, :out_sec, -
  :limit_unsec, :limit_supp, :limit_sec, :tenor_unsec, :tenor_supp, :tenor_sec);

print out_unsec
print out_supp
...

例如,您可以在脚本的后续代码中使用绑定变量,并且可以通过从那里调用它们在 C# 中使用。

虽然 SQL Developer 可以半自动化地进行测试,但设置起来有点麻烦。它还假设总会有一个结果,正如你所说的那样,但如果没有结果或不止一个结果,你会从过程中得到一个例外。

(顺便说一下,您的过程中不需要局部变量;您的查询可以直接选择unsec_out,不需要单独的中间out_unsec。您可能还需要考虑命名约定,例如,p_out_unsec 用于形式参数,l_out_unsec 用于局部变量,如果您决定保留它。更容易查看您正在使用和修改的内容,您当前的名称很容易混淆)。

另一种方法是使用参考光标:

create or replace PROCEDURE P_MATRIKA 
(
    leto IN NUMBER, 
    rating IN NUMBER,
    davcna IN VARCHAR2,
    p_refcur OUT SYS_REFCURSOR
)
AS
BEGIN
    OPEN p_refcur FOR
    ... your query
END;

你可以这样做:

var refcur refcursor
exec p_matrika(2010, 2.5, '26311330', :refcur);
print refcur

或者你可以把它变成一个返回引用游标的函数。然后,您的 C# 代码可以像对待任何其他结果集一样对待绑定的引用光标。

【讨论】:

  • Alex,感谢您的详细回答。很明显,您知识渊博,对我来说可能知识渊博:-)。我多次阅读并重新阅读您的答案,尝试使用您的解决方案,但无法正常工作。可能 - 由于我缺乏知识 - 我没有正确使用您建议的实现。在您的帮助下,我仍然无法正常工作。我无法理解带有 1 个 OUT 参数的过程如何在我的 C# 代码中按预期工作,但是当我包含超过 1 个 OUT 参数时它不起作用。在 C# 中,我只是在 CommandText 中使用 SP,设置 in 和 out 参数就可以了。
  • 它在 SQL*Plus/SQL Developer 中是否适合您?在 C# 中,您需要设置所有 9 个 OUT 参数 - 方向正确 - 并在命令文本中为它们设置正确数量的绑定占位符。如果它在 SQL*Plus 中运行,但您仍然无法在 C# 中正确调用,最好提出一个新问题,显示过程规范和您对 C# 代码的最佳尝试,以及您仍然得到的错误。 (并设置正确的标签)
  • 不,我无法在 SQL Developer 中工作,也无法在 C# 中工作。也许我的方法从一开始就是错误的。本质上,我需要的是一个过程或函数,它将我的 SQL 语句结果返回到我的 C# 应用程序,即:1 行,9 个字段,如 OUT 参数中指定的那样。但是亚历克斯,尽管如此,我还是要感谢您为帮助我所做的所有努力。非常感谢。保重。
  • @Flin - 如果您想要返回一行,请使用 ref 游标方法。既可以作为过程的 put 参数,也可以作为函数返回值。
【解决方案2】:

好的,我设法解决了我的问题。或者更好的说法是,Alex Poole 解决了这个问题,所以对他表示敬意:-)。

Oracle 存储过程:

create or replace PROCEDURE P_MATRIKA 
(
    p_leto IN NUMBER, 
    p_rating IN NUMBER,
    p_davcna IN VARCHAR2,
    p_refcur OUT SYS_REFCURSOR
)
IS
BEGIN
    OPEN p_refcur FOR
    with 
        matrika_osnova 
    as
    (
    select distinct a.par_davcna, nvl(a.unsecured,0) unsec_out,
                 nvl(a.supported,0) supp_out, nvl(a.secured,0) sec_out,
                 x.tip_sub, x.cispri, x.kraban, x.dolfinobv,
                 y.ltv_tip, y.rating, y.unsec_pct, q.supp_pct,
                 w.sec_pct, p.unsec_maxznes, s.sec_maxznes,
                 case when y.unsec_pct * nvl(x.cispri,0) > nvl(p.unsec_maxznes,0) then
                                     nvl(p.unsec_maxznes,0) - nvl(x.kraban,0) + (nvl(x.dolfinobv,0)/5)
                            else
                                    case when y.unsec_pct * nvl(x.cispri,0) - 
                                                        nvl(x.kraban,0) + (nvl(x.dolfinobv,0)/5) < 0 then
                                                        0
                                            else
                                                        y.unsec_pct * nvl(x.cispri,0) - nvl(x.kraban,0) + 
                                                        (nvl(x.dolfinobv,0)/5)
                                    end
                 end unsec_max,
                 case when q.supp_pct * nvl(x.cispri,0) > nvl(s.sec_maxznes,0) then
                                     nvl(s.sec_maxznes,0) - nvl(x.kraban,0) + (nvl(x.dolfinobv,0)/5)
                            else
                                    case when q.supp_pct * nvl(x.cispri,0) - nvl(x.kraban,0) + 
                                                        (nvl(x.dolfinobv,0)/5) < 0 then
                                                        0
                                            else
                                                        q.supp_pct * nvl(x.cispri,0) - nvl(x.kraban,0) + 
                                                        (nvl(x.dolfinobv,0)/5)
                                    end
                 end supp_max,
                 case when w.sec_pct * nvl(x.cispri,0) > nvl(s.sec_maxznes,0) then
                                     nvl(s.sec_maxznes,0) - nvl(x.kraban,0) + (nvl(x.dolfinobv,0)/5)
                            else
                                    case when w.sec_pct * nvl(x.cispri,0) - nvl(x.kraban,0) + 
                                                        (nvl(x.dolfinobv,0)/5) < 0 then
                                                        0
                                            else
                                                        w.sec_pct * nvl(x.cispri,0) - nvl(x.kraban,0) + 
                                                        (nvl(x.dolfinobv,0)/5)
                                    end
                 end sec_max,
                 d.unsec_tenor, e.supp_tenor, f.sec_tenor                               
    from sco_matrika_banka a
    inner join
                        (select b.tip_sub, b.par_davcna, b.cispri, b.kraban, b.dolfinobv
                         from scoring_gvin b
                         where b.leto = p_leto) x --IN parameter
    on a.par_davcna = x.par_davcna
    inner join 
                        (select a.tip_sub, a.ltv_tip, 
                         a.max_znesek unsec_maxznes
                         from sco_sif_ltv_maxznes a
                         where a.ltv_tip = 1) p
    on x.tip_sub = p.tip_sub
    inner join 
                        (select a.tip_sub, a.ltv_tip, 
                         a.max_znesek sec_maxznes
                         from sco_sif_ltv_maxznes a
                         where a.ltv_tip = 3) s
    on x.tip_sub = s.tip_sub
    inner join
                        (select a.tip_sub, a.ltv_tip, 
                                        a.rating, a.ltv_pct unsec_pct
                         from sco_sif_ltv_pct a
                         where a.ltv_tip = 1
                         and a.rating = p_rating) y --IN parameter
    on x.tip_sub = y.tip_sub
    inner join
                        (select a.tip_sub, a.ltv_tip, 
                                        a.rating, a.ltv_pct supp_pct
                         from sco_sif_ltv_pct a
                         where a.ltv_tip = 2
                         and a.rating = p_rating) q --IN parameter
    on x.tip_sub = y.tip_sub
    inner join
                        (select a.tip_sub, a.ltv_tip, 
                                        a.rating, a.ltv_pct sec_pct
                         from sco_sif_ltv_pct a
                         where a.ltv_tip = 3
                         and a.rating = p_rating) w --IN parameter
    on x.tip_sub = y.tip_sub
    inner join
                         (select a.tip_sub, a.tenor unsec_tenor
                            from sco_sif_ltv_tenor a
                            where a.ltv_tip = 1) d
    on x.tip_sub = d.tip_sub
    inner join
                         (select a.tip_sub, a.tenor supp_tenor
                            from sco_sif_ltv_tenor a
                            where a.ltv_tip = 2) e
    on x.tip_sub = e.tip_sub
    inner join
                         (select a.tip_sub, a.tenor sec_tenor
                            from sco_sif_ltv_tenor a
                            where a.ltv_tip = 3) f
    on x.tip_sub = f.tip_sub
    where a.par_davcna = p_davcna) --IN parameter

    select a.unsec_out, a.supp_out, a.sec_out,
                 case when a.unsec_max - a.unsec_out < 0 then
                                     0
                            else
                                     a.unsec_max - a.unsec_out
                 end unsec_limit,
                             case when a.supp_max - a.supp_out < 0 then
                                     0
                            else
                                     a.supp_max - a.supp_out
                 end supp_limit,
                             case when a.sec_max - a.sec_out < 0 then
                                     0
                            else
                                     a.sec_max - a.sec_out
                 end sec_limit,
                 a.unsec_tenor, a.supp_tenor, a.sec_tenor
    from matrika_osnova a;
END;

C#代码:

public void LoadMatrika(string davcna)
{
    using (OracleConnection conn = CreateConnection())
    {
        using (OracleCommand cmd = new OracleCommand())
        {
            cmd.Connection = conn;
            cmd.CommandText = "P_MATRIKA";
            cmd.CommandType = CommandType.StoredProcedure;
            cmd.Parameters.Add(new OracleParameter("p_leto", Util.letoc));
            cmd.Parameters.Add(new OracleParameter("p_rating", Score.Rating));
            cmd.Parameters.Add(new OracleParameter("p_davcna", davcna));
            cmd.Parameters.Add(new OracleParameter("p_refcur", OracleDbType.RefCursor, ParameterDirection.Output));
            cmd.BindByName = true;

            using (OracleDataReader dr = cmd.ExecuteReader())
            {
                if (dr.HasRows)
                {
                    dr.Read();
                    Matrika.UnsecuredOut = dr.GetDecimal(0);
                    Matrika.SupportedOut = dr.GetDecimal(1);
                    Matrika.SecuredOut = dr.GetDecimal(2);
                    Matrika.UnsecuredLimit = dr.GetDecimal(3);
                    Matrika.SupportedLimit = dr.GetDecimal(4);
                    Matrika.SecuredLimit = dr.GetDecimal(5);
                    Matrika.UnsecuredTenor = dr.GetDecimal(6);
                    Matrika.SupportedTenor = dr.GetDecimal(7);
                    Matrika.SecuredTenor = dr.GetDecimal(8);
                }
            }
        }
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-09-09
    • 1970-01-01
    • 2018-11-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-27
    相关资源
    最近更新 更多