将数组传递给 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 函数的主要内容,如果未能解决你的问题,请参考以下文章