2017-03-17 73 views
0

我收到此錯誤:使用PLS-00306在Oracle功能使用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。

+0

沒有任何測試數據測試工具是沒有太大的用處。 – APC

回答

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; 
+0

爲了使用'MULTISET UNION',嵌套表必須具有可比性,請參閱[MULTISET UNION](http://docs.oracle.com/database/121/SQLRF/operators006.htm#SQLRF51170)。 'OBJECT(inn NUMBER,OUT NUMBER)'不是這種情況 - 除非您定義了MAP MEMBER FUNCTION,請參見[對象比較](https://docs.oracle.com/cd/B28359_01/appdev.111/b28425 /obj_types.htm#i1004721) –

+1

對不起,它應該像Oracle所說的那樣工作:「*如果您尚未爲對象類型定義映射或順序函數,則它只能支持相等比較,Oracle SQL通過執行字段來執行比較按字段比較該類型的屬性*「但是,我留下我的第一條評論,因爲我認爲值得一提。 –

+0

你是對的。 – APC

1

您所做的錯誤是同時存儲的結果。見我的意見直列

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

有趣。如果'join_table'中有多個條目,會發生什麼? – APC

+0

@APC。好問題。我不確定數據。假設只有1條記錄,則上述應該起作用,否則將失敗。毫無疑問。但是,如果OP採用這種方式,他可能會考慮這個問題。 – XING

+0

使用BULK COLLECT表明我們不保證一行。 – APC