【问题标题】:PLS-00306 on Oracle function using a UDT关于使用 UDT 的 Oracle 函数的 PLS-00306
【发布时间】:2017-03-17 00:33:37
【问题描述】:

我收到此错误:

LINE/COL ERROR
-------- -----------------------------------------------------------------
13/3     PL/SQL: Statement ignored
13/13    PLS-00306: wrong number or types of arguments in call to 'JOIN_JT'

使用的类型:

CREATE TYPE join_t IS OBJECT (
   inn      NUMBER(38),
   out      NUMBER(38)
);
/

CREATE TYPE join_jt IS TABLE OF join_t;
/

这是返回错误的函数的 PL/SQL 代码。当我尝试将我在join_table 中得到的结果传递给retval 时,会触发上面的类型错误):

CREATE OR REPLACE FUNCTION join RETURN join_jt
AS
    CURSOR cur_fv_table IS SELECT id,fv FROM london WHERE id <= 3000;

    retval join_jt := join_jt ();
    var_fv london.fv%type;
    var_id london.id%type;
    join_table join_jt := join_jt();
BEGIN
    OPEN cur_fv_table;
    LOOP
        FETCH cur_fv_table INTO var_id,var_fv;

        SELECT join_t(r.id, var_id) BULK COLLECT INTO join_table
        FROM   london r
        WHERE  manh_dist(r.fv,var_fv) <= 5;

        retval.EXTEND;
        retval := join_t(join_table);
    END LOOP;

    RETURN join_table;            
END;
/

你可以使用这个函数来测试上面的函数:

CREATE OR REPLACE FUNCTION manh_dist(
    fv1 LONDON.FV%TYPE,
    fv2 LONDON.FV%TYPE
) RETURN NUMBER
AS
BEGIN
    RETURN 0;                              -- Implement this.
END;
/

有谁知道如何解决这个错误?

我正在使用 Oracle 11g。

【问题讨论】:

  • 没有任何测试数据的测试工具没有多大用处。

标签: sql database oracle plsql user-defined-types


【解决方案1】:

所以这是你的问题:

       retval := join_t (join_table);

您正在尝试将表转换为对象类型。这是错误的。要填充输出表,您需要将查询集合与返回集合联合。您需要的是 MULTISET UNION:

CREATE OR REPLACE FUNCTION knn_join RETURN join_jt
IS
CURSOR cur_fv_table IS SELECT id,fv FROM londonfv WHERE id <= 3000;
retval join_jt := join_jt ();
var_fv londonfv.fv%type;
var_id londonfv.id%type;
join_table join_jt := join_jt();
BEGIN
    OPEN cur_fv_table;
    LOOP
        FETCH cur_fv_table INTO var_id,var_fv;
        SELECT join_t(r.id, var_id) BULK COLLECT 
        INTO join_table FROM londonfv r WHERE manhattan_dist(r.fv,var_fv) <=5;
       retval := retval multiset union all join_table;
    END LOOP;   
    RETURN retval;          
END;
/

注意:我假设您确实打算返回聚合集合 retval 而不是最后一个中间集。


现在没有时间测试这个,我承认@Wernfried 让我怀疑它是否会运行。如果遇到问题,这种直率的方法会奏效:

for idx in join_table.first()..join_table.last()
       loop
            Retval.extend();
           retval(retval.count()) := join_table(idx);
       end loop;

【讨论】:

  • 为了使用MULTISET UNION,嵌套表必须具有可比性,请参阅MULTISET UNIONOBJECT (inn NUMBER, OUT NUMBER) 不是这种情况 - 除非您定义 MAP MEMBER FUNCTION,请参阅 Object Comparison
  • 对不起,它应该像Oracle所说的那样工作:“如果您没有为对象类型定义映射或排序函数,它只能支持相等比较。Oracle SQL通过执行比较该类型的属性的逐个字段比较。“但是,我留下我的第一条评论,因为我认为值得一提。
  • 你错过了retval.EXTEND; 否则循环不起作用。
【解决方案2】:

您犯的错误是在存储结果时。查看我的 cmets 内联

retval := join_t (join_table);

CREATE OR REPLACE FUNCTION knn_join
 RETURN join_jt
IS
   CURSOR cur_fv_table
   IS
      SELECT id, fv
        FROM londonfv
       WHERE id <= 3000;

   retval       join_jt := join_jt ();
   var_fv       londonfv.fv%TYPE;
   var_id       londonfv.id%TYPE;
   join_table   join_jt := join_jt ();

BEGIN
   OPEN cur_fv_table;

  LOOP
      --Fetching records of cursor to variable var_id & var_fv  
      FETCH cur_fv_table INTO var_id, var_fv;


      SELECT join_t (r.id, r.fv) -- You made mistake here. You need to select your table columns here not any variable.
        BULK COLLECT INTO join_table --- Populating the collection
        FROM londonfv r
       WHERE manhattan_dist (var_id, var_fv) <= 5; -- Checking from the function

      --- Assuming there is only 1 record in collection join_table. 
      retval.EXTEND;
      --- Storing the value of into the collection
      retval := join_table;

      /*  If there are more then 
         for rec in 1..join_table.count
         loop
          retval.EXTEND;
          retval(rec):= join_table(rec);              
        end loop; 
       */
    END LOOP;

   RETURN retval;
END;
/

【讨论】:

  • 有趣。如果join_table 中有多个条目会怎样?
  • @APC。好问题。我不确定数据。假设只有 1 条记录,以上应该可以工作,否则它将失败。毫无疑问。但同样,如果 OP 使用这种方式,他可能会记住这个问题。
  • BULK COLLECT 的使用表明我们不能保证一排。
  • @APC。根据您的建议进行编辑。谢谢。
猜你喜欢
  • 2011-08-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-11-24
  • 2020-12-26
相关资源
最近更新 更多