将数组传递给Oracle函数

时间:2013-05-01 06:50:04

标签: arrays oracle function plsql package

我将数组传递给PL / SQL包函数。我这样做是为了在具有IN子句的函数内的查询中使用这个数组。

我的包裹声明如下:

create or replace 
PACKAGE selected_pkg IS

  TYPE NUM_ARRAY IS TABLE OF NUMBER;

   FUNCTION get_selected_kml(
      in_layer        IN NUMBER,
     in_id      IN NUMBER,
      in_feature_ids  IN selected_pkg.NUM_ARRAY,
      in_lx           IN NUMBER,
      in_ly           IN NUMBER,
      in_ux           IN NUMBER,
      in_uy           IN NUMBER
      )
    RETURN CLOB;

END selected_pkg;

在我的PL / SQL函数中,我正在触发如下的查询

select a.id, a.geom  from Table_FIELD a  where  a.id in (select * from table (in_feature_ids)) and  sdo_filter(A.GEOM,mdsys.sdo_geometry(2003,4326,NULL,mdsys.sdo_elem_info_array(1,1003,3), mdsys.sdo_ordinate_array(0,57,2.8,59)),'querytype= window') ='TRUE'

如果我从像

这样的匿名块运行它,那么相同的查询运行正常
CREATE TYPE num_arr1 IS TABLE OF NUMBER;

declare
    myarray num_arr1 := num_arr1(23466,13396,14596);
BEGIN
    FOR i IN (select a.id, a.geom  from Table_FIELD a  where  a.id in (select * from table (myarray)) and  sdo_filter(A.GEOM,mdsys.sdo_geometry(2003,4326,NULL,mdsys.sdo_elem_info_array(1,1003,3), mdsys.sdo_ordinate_array(0,57,2.8,59)),'querytype= window') ='TRUE'
    loop
       dbms_output.put_line(i.id);
    end loop;
end;

如果我尝试通过调用函数来运行它,如下所示

--Running function from passing array for IDs
declare
  result CLOB;
  myarray selected_pkg.num_array := selected_pkg.num_array(23466,13396,14596);
begin
    result:=SELECTED_PKG.get_selected_kml(3, 19, myarray, 0.0,57.0,2.8,59);
end;

我收到错误

ORA-00904: "IN_FEATURE_IDS": invalid identifier

有人可以帮我理解它的原因吗?

谢谢, 艾伦

2 个答案:

答案 0 :(得分:2)

您无法在sql查询中查询plsql中声明的类型,因为sql引擎无法识别它。

您的第一个示例有效,因为您已在数据库中声明了类型numarr1,而类型为selected_pkg.num_array在包中声明。

好总结here

答案 1 :(得分:2)

我无法重现你所得到的错误;匿名块不引用in_feature_ids,并且程序包只应报告如果它在编译时不识别它而不是在运行时 - 除非您使用的是动态SQL。如果没有能够看到功能体,我不确定这是怎么回事。

但是你不能在SQL语句中使用PL / SQL定义的类型。在某些时候table(in_feature_ids)会出错;当我尝试时,我得到一个ORA-21700,对我来说这是一个新的,我期待ORA-22905。无论出现什么错误,您都必须使用在模式级别定义的类型,而不是在包中,因此这将起作用(为简洁起见,跳过空间内容):

CREATE TYPE num_array IS TABLE OF NUMBER;
/

CREATE OR REPLACE PACKAGE selected_pkg IS
    FUNCTION get_selected_kml(
        in_layer        IN NUMBER,
        in_id           IN NUMBER,
        in_feature_ids  IN NUM_ARRAY,
        in_lx           IN NUMBER,
        in_ly           IN NUMBER,
        in_ux           IN NUMBER,
        in_uy           IN NUMBER
    ) RETURN CLOB;
END selected_pkg;
/

CREATE OR REPLACE PACKAGE BODY selected_pkg IS
    FUNCTION get_selected_kml(
        in_layer        IN NUMBER,
        in_id           IN NUMBER,
        in_feature_ids  IN NUM_ARRAY,
        in_lx           IN NUMBER,
        in_ly           IN NUMBER,
        in_ux           IN NUMBER,
        in_uy           IN NUMBER
    ) RETURN CLOB IS
    BEGIN
        FOR i IN (select * from table(in_feature_ids)) LOOP
            DBMS_OUTPUT.PUT_LINE(i.column_value);
        END LOOP;
        RETURN null;
    END get_selected_kml;
END selected_pkg;
/

...并且还使用模式级别类型调用:

set serveroutput on
declare
    result CLOB;
    myarray num_array := num_array(23466,13396,14596);
begin
    result:=SELECTED_PKG.get_selected_kml(3, 19, myarray, 0.0,57.0,2.8,59);
end;
/

23466
13396
14596

PL/SQL procedure successfully completed.

另请注意,您必须使用完全相同的类型,而不仅仅是看起来相同的类型,如in a recent question所述。例如,您无法使用num_arr1类型的变量调用函数;它们在表面上看起来是一样的,但对于Oracle来说它们是不同的并且不兼容。