0

我将一个数组传递给一个 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

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

谢谢,艾伦

4

2 回答 2

2

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

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

很好的总结在这里

于 2013-05-01T08:37:24.293 回答
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.

另请注意,您必须使用完全相同的类型,而不仅仅是看起来相同的类型,如最近的一个问题中所讨论的那样。例如,您将无法使用num_arr1类型变量调用您的函数;它们在表面上看起来相同,但对于 Oracle,它们是不同的且不兼容的。

于 2013-05-01T09:00:37.590 回答