PLS-00306 关于使用 UDT 的 Oracle 函数

PLS-00306 on Oracle function using a UDT

我收到这个错误:

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。

所以这是你的问题:

       retval := join_t (join_table);

您正在尝试将 table 转换为对象类型。这是错误的。要填充输出 table,您需要将查询集合与 return 集合合并。 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;
/

注意:我假设您真的想要 return 聚合集合 retval 而不是最后一个中间集合。


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

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

您在存储结果时犯了错误。在线查看我的评论

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;
/