如何将许多select语句的结果作为一个自定义表返回

时间:2018-01-07 20:11:32

标签: sql oracle dynamic-sql

我有一个表(我们将其命名为source_tab),其中我存储了符合某些条件的所有数据库表的列表。

tab_name:     description:
table1        some_desc1
table2        some_desc2

现在我需要在每个表上执行select语句并将结果作为表返回(我创建了自定义TYPE)。但是我有一个问题 - 使用批量收集时,只返回最后一个select语句。打开游标也是同样的问题。有没有可能实现这个目标,另一个是使用union all连接所有select语句并将其作为一个语句执行?因为我是sql的初学者,我的第二个问题是,在sql注入问题方面使用这个动态sql是否可以?以下是我的代码的简化版本:

CREATE OR REPLACE FUNCTION my_function RETURN newly_created_table_type IS
   ret_tab_type newly_created_table_type;
BEGIN
     for r in (select * from source_tab)
     loop
        execute immediate 'select value1, value2,''' || r.tab_name || ''' from ' || r.tab_name bulk collect into ret_tab_type; 
     end loop;
   return ret_tab_type;
END;

我正在使用Oracle 11。

2 个答案:

答案 0 :(得分:0)

如果要从所有表中检索的列的数量和类型相同,可以在执行前使用UNION ALL将所有查询合并为一个。

CREATE OR REPLACE FUNCTION my_function
   RETURN newly_created_table_type
IS
   ret_tab_type   newly_created_table_type;
   v_query        VARCHAR2 (4000);
BEGIN
   SELECT LISTAGG (' select VALUE1,VALUE2 FROM ' || tab_name, ' UNION ALL ')
             WITHIN GROUP (ORDER BY tab_name)
     INTO v_query
     FROM source_tab;

   EXECUTE IMMEDIATE v_query BULK COLLECT INTO ret_tab_type;

   RETURN ret_tab_type;
END;

然后,您可以使用单个select语句来获取所有值。

select * FROM TABLE ( my_function );

答案 1 :(得分:0)

在您的情况下,您尝试动态填充集合并希望将结果放在单个集合中。在你的情况下,它不可能在一个循环中这样做。同样正如@OldProgrammer所提到的,从性能角度来看,piperow将是一个更好的解决方案。见下面的演示:

- 表格和值:

CREATE TABLE SOURCE_TAB(TAB_NAME VARCHAR2(100),   DESCRIPTION  VARCHAR2(100));
/

SELECT * FROM SOURCE_TAB;
/

INSERT INTO SOURCE_TAB VALUES('table1','some_desc1');
INSERT INTO SOURCE_TAB VALUES('table2','some_desc2');
/

CREATE TABLE TABLE1(COL1 NUMBER, COL2 NUMBER);
/

INSERT INTO TABLE1 VALUES(1,2);
INSERT INTO TABLE1 VALUES(3,4);
INSERT INTO TABLE1 VALUES(5,6);
/

Select * from TABLE1;
/

CREATE TABLE TABLE2(COL1 NUMBER, COL2 NUMBER);
/

INSERT INTO TABLE2 VALUES(7,8);
INSERT INTO TABLE2 VALUES(9,10);
INSERT INTO TABLE2 VALUES(11,12);
/

Select * from TABLE2;
/

- 对象已创建

--UDT 
CREATE OR REPLACE TYPE NEWLY_CREATED_TABLE_TYPE IS OBJECT (
     VALUE1                        NUMBER,
     VALUE2                        NUMBER
);
/

--Type of UDT
CREATE OR  TYPE NEWLY_CRTD_TYP AS TABLE OF NEWLY_CREATED_TABLE_TYPE;
/

- 功能:

--Function
CREATE OR REPLACE FUNCTION MY_FUNCTION
     RETURN NEWLY_CRTD_TYP PIPELINED
AS
     CURSOR CUR_TAB
     IS
          SELECT *
            FROM SOURCE_TAB;

     RET_TAB_TYPE                  NEWLY_CRTD_TYP;
BEGIN
     FOR I IN CUR_TAB
     LOOP
          --Here i made sure that all the tables have col1 & col2 columns since you are using dynamic sql. 
          EXECUTE IMMEDIATE    'select  NEWLY_CREATED_TABLE_TYPE(COL1, COL2)  from '|| I.TAB_NAME
          BULK COLLECT INTO RET_TAB_TYPE;

          EXIT WHEN CUR_TAB%NOTFOUND;

          FOR REC IN 1 .. RET_TAB_TYPE.COUNT
          LOOP
               PIPE ROW (RET_TAB_TYPE (REC) );
          END LOOP;
     END LOOP;

     RETURN;
END;
/

输出:

    SQL>  Select *  from table(MY_FUNCTION);

    VALUE1     VALUE2
---------- ----------
         1          2
         3          4
         5          6
         7          8
         9         10
        11         12

6 rows selected.