4

我有两个函数都返回 a TYPE,即:

CREATE OR REPLACE FUNCTION myUser.f_myFunction
(
    myId IN RAW := NULL
) RETURN myUser.myType
AS
    ResultTable myUser.myType;
BEGIN
    ...
    -- fill ResultTable
    ...

    RETURN ResultTable;
END;

现在我想和他们一起SELECT发表声明:

SELECT *
FROM myUser.f_myFunction1() f1
JOIN myUser.f_myFunction2() f2 ON f1.xy = f2.yz;

但是如果我在语句中包含一个函数SELECT,我会得到一个错误:

SELECT * FROM myUser.f_myFunction();
                                 *
ERROR in Line 1:
ORA-00933: SQL command not properly ended
    ORA-04044: procedure, function, package, or type is not allowed here

.

编辑:将函数调用嵌套在TABLE()子句中会出现以下错误:

SELECT * FROM TABLE(myUser.f_myFunction())
              *
ERROR at line 1:
ORA-22905: cannot access rows from a non-nested table item

然后我尝试投射它,但是:

SELECT * FROM TABLE(CAST(myUser.f_myFunction() AS myUser.myType))
                             *
ERROR at line 1:
ORA-22907: invalid CAST to a type that is not a nested table or VARRAY

和:

SELECT * FROM TABLE(CAST(myUser.f_myFunction() AS myUser.myTypeTable))
                             *
ERROR at line 1:
ORA-00932: inconsistent datatypes: expected - got myUser.myType

.

编辑2:这是类型的定义(对不起,应该早点包括它们):

CREATE TYPE myUser.myType AS OBJECT (
    ....
);

CREATE TYPE myUser.myTypeTable IS TABLE OF myUser.myType;

.

编辑3:让它像这样工作:

CREATE OR REPLACE FUNCTION myUser.f_myFunction
(
    myId IN RAW := NULL
) RETURN myUser.myTypeTable
AS
    ResultTable myUser.myTypeTable;
BEGIN

    SELECT myUser.myType(x.Column1, x.Column2, ...)
        BULK COLLECT INTO ResultTable
        FROM myUser.myTable x
        WHERE ...

    RETURN ResultTable;
END;
4

1 回答 1

2

至少有三种方法可以做到这一点:1)C创建一个嵌套表2)多次调用函数3)创建一个函数来访问每个属性。

示例对象

create or replace type myType as object
(
    wx number,
    xy number
);


CREATE OR REPLACE FUNCTION f_myFunction
(
    myId IN RAW := NULL
) RETURN myType
AS
    ResultTable myType := myType(1, 2);
BEGIN
    RETURN ResultTable;
END;
/

方法一:创建嵌套表

正如 Luke Woodward 所指出的,TABLE 和 CAST 特性需要一个嵌套的类型表。即使您只打算使用单个元素。

create or replace type myType_nt is table of myType;

CREATE OR REPLACE FUNCTION f_myFunction_nt
(
    myId IN RAW := NULL
) RETURN myType_nt
AS
    ResultTable myType_nt := myType_nt(myType(1, 2));
BEGIN
    RETURN ResultTable;
END;
/

select wx, xy from table(f_myFunction_nt());

WX  XY
--  --
1   2

方法二:对每个属性重复函数调用

如果为每个属性调用一次函数,则不需要额外的对象。这是重复的并且可能成本高昂。将函数设置为确定性可能会阻止函数实际被多次调用。

select wx, xy from
(
    select f_myFunction().wx wx, f_myFunction().xy xy from dual
);

WX  XY
--  --
1   2

似乎应该有一种更简单的方法来做到这一点。Oracle 确实支持调用该函数一次并返回具有这两个属性的类型。但是没有办法有意义地使用这种类型。属性不容易从 SQL 访问。

SQL> select * from (select f_myFunction() from dual);

F_MYFUNCTION()(WX, XY)
-----------------------------------------------------
MYTYPE(1, 2)

直观的方法,简单地使用每个属性名称,是行不通的。

SQL> select wx, xy from (select f_myFunction() from dual);
select wx, xy from (select f_myFunction() from dual)
           *
ERROR at line 1:
ORA-00904: "XY": invalid identifier

方法3:为每个属性创建一个函数

您可以使用函数访问属性。这需要添加新对象,但它使您的主要功能保持不变。

create or replace function get_wx(p_myType myType) return number is
begin
    return p_myType.wx;
end;
/

create or replace function get_xy(p_myType myType) return number is
begin
    return p_myType.xy;
end;
/

select get_wx(asdf) wx, get_xy(asdf) xy
from (select f_myFunction() asdf from dual);

WX  XY
--  --
1   2
于 2013-10-30T17:26:34.217 回答