有没有办法在PL / SQL中完成这样的事情......
select a.col1, a.col2, a.col3, myFunc(a.id) from myTable a;
结果超过4列?所以基本上,有一种方法可以让函数返回或管道多个列回来吗?所需的数量是已知的,并且设置为3,因此该查询将返回6列。我知道我可以单独调用myFunc()
3次,但处理量会增加三倍。
我一直在玩管道功能,但似乎没有用它来做到这一点。
Oracle Database 11g企业版11.2.0.2.0版 - 64位
生产PL / SQL版本11.2.0.2.0 - 生产
谢谢!
答案 0 :(得分:2)
以下是在各种Oracle版本中执行此操作的方法。我只使用DBA_OBJECTS
代替你的真实桌子。
CREATE OR REPLACE TYPE my_func_rec IS OBJECT
(
mf_col1 NUMBER,
mf_col2 NUMBER,
mf_col3 NUMBER
);
CREATE OR REPLACE TYPE my_func_tab IS TABLE OF my_func_rec;
CREATE OR REPLACE FUNCTION my_func (id NUMBER)
RETURN my_func_tab IS
l_result my_func_tab;
BEGIN
SELECT my_func_rec (id + 100, id + 101, id + 102)
BULK COLLECT INTO l_result
FROM DUAL;
RETURN l_result;
END my_func;
在12c中,使用CROSS APPLY
非常简单。
SELECT object_id,
object_type,
status,
mf_col1,
mf_col2,
mf_col3
FROM dba_objects o
CROSS APPLY (SELECT mf_col1,
mf_col2,
mf_col3
FROM TABLE (my_func (o.object_id)) odet);
在11g中,您无权访问CROSS APPLY
,因此您需要选择函数结果作为对象,然后TREAT
将其作为对象来访问各个字段。
SELECT object_id,
object_type,
status,
TREAT (val AS my_func_rec).mf_col1,
TREAT (val AS my_func_rec).mf_col2,
TREAT (val AS my_func_rec).mf_col3
FROM (SELECT object_id,
object_type,
status,
(SELECT my_func_rec (mf_col1, mf_col2, mf_col3)
FROM TABLE (my_func (o.object_id)) mf)
val
FROM dba_objects o)
注意:我在12c答案后创建了11g答案。通过my_func
返回my_func_rec
而不是my_func_tab
,可以进一步简化11g答案。在这种情况下,它将简化为:
SELECT object_id,
object_type,
status,
TREAT (val AS my_func_rec).mf_col1,
TREAT (val AS my_func_rec).mf_col2,
TREAT (val AS my_func_rec).mf_col3
FROM (SELECT object_id,
object_type,
status,
my_func (o.object_id) val
FROM dba_objects o)
答案 1 :(得分:0)
一个非常简洁的插图。希望它有所帮助。
--The best way here is to make a table type function
--as mentioned below
--Create object type
CREATE OR REPLACE TYPE OBJ_DUM
IS
OBJECT
(
COL1 NUMBER,
COL2 NUMBER,
COL3 VARCHAR2(100) );
/
--Create table type
CREATE OR REPLACE TYPE TAB_DUM
IS
TABLE OF OBJ_DUM;
/
--Create dummy function. This canbe a pipelined function also
CREATE OR REPLACE
FUNCTION SO_DUM
RETURN TAB_DUM
AS
lv_tab tab_dum:=tab_dum(NULL,NULL,NULL);
BEGIN
SELECT obj_dum(level,level+1,'AVRAJIT+'
||LEVEL) BULK COLLECT
INTO lv_tab
FROM DUAL
CONNECT BY LEVEL < 2;
RETURN lv_tab;
END;
/
--To check the output
SELECT TAB.*,OBJ.* FROM USER_OBJECTS OBJ,TABLE(SO_DUM) TAB;