将数组传递给 Oracle 函数

Posted

技术标签:

【中文标题】将数组传递给 Oracle 函数【英文标题】:Passing Array to Oracle Function 【发布时间】:2013-05-01 06:50:04 【问题描述】:

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

有人可以帮我了解一下原因吗?

谢谢, 艾伦

【问题讨论】:

Alex,是的,我在上面的问题中解决了这个问题(复制粘贴时出错)。但是我运行正确。 【参考方案1】:

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

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

好总结here

【讨论】:

Stevo,您能否建议我如何实现该功能? @AlanShar 看到 Alex Poole 的回答。【参考方案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 看来它们是不同且不兼容的。

【讨论】:

以上是关于将数组传递给 Oracle 函数的主要内容,如果未能解决你的问题,请参考以下文章

如何给SQLSERVER存储过程传递数组参数

将字节数组传递给 oracle 存储过程

将数组传递给构造函数会产生大小为 1 的数组? [复制]

将数组传递给函数形式参数

将数组/列表传递给 Python 函数

将指向数组的指针传递给函数时出现分段错误(C++)