PL / SQL使用单个函数添加多个列进行查询

时间:2017-08-09 19:40:29

标签: sql oracle plsql

有没有办法在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 - 生产

谢谢!

2 个答案:

答案 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

在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);

11克

在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;