首页 文章

在存储过程中重用大型SQL查询

提问于
浏览
0

我有一些很长的SQL选择查询(150行),我想在PL / SQL包中使用 . 该程序包具有执行SQL查询并将结果插入单独的表,将SQL结果与另一个表进行比较,删除行等的过程

它很容易存储SQL结果:

INSERT into TABLE1
SELECT .... (150 line ugly select query goes here)

问题是,我想将选择SQL存储在游标/函数/视图/无论什么工作中,因此我不必将150行查询粘贴到使用SQL的每个过程中 .

我可以将SQL存储为游标,然后在包过程中循环遍历游标,获取每一行,例如插入到我的表中 . 但是考虑到我使用游标的唯一动机是减少我的包的行数,这似乎非常低效 .

有没有更好的方法在不复制和粘贴所有150行的情况下在不同的过程中调用SQL select查询?如果这是一个脚本,我会将SQL存储在一个文本文件中,然后只需将文本文件读入一个变量,并在需要时将该变量传递给sqlplus . 但我对PL / SQL不是很熟悉 .

码:

CREATE OR REPLACE PACKAGE BODY MyPackage
as
Cursor my_cursor
select (150+ lines goes here)

PROCEDURE PopulateTable
is 
TYPE fetch_array IS TABLE OF my_cursor%ROWTYPE;
s_array fetch_array;
BEGIN

  open my_cursor;

  LOOP
    FETCH tran_cursor BULK COLLECT INTO s_array;
    FORALL counter in 1..s_array.COUNT
        INSERT INTO my_table VALUES s_array(counter);
    EXIT when s_array%NOTFOUND;
  END LOOP;  

  close my_cursor;
  COMMIT;

END PopulateTable;
END MyPackage;

2 回答

  • 0

    我不确定这是否是最好的方法,但我想到的是一个可变光标 . 你可以使用SYS_REFCURSOR来做到这一点 . 您可以构建一个包含查询的函数,并返回ref curosr . 在所有程序中,您只需调用该函数即可 . 这将节省您在每个过程中编写150行查询 . 更重要的是,它会将您的程序限制为一个查询副本,因此易于维护 .

    返回引用游标的函数可能是这样的:

    CREATE OR REPLACE FUNCTION my_ugly_query() 
                               RETURN SYS_REFCURSOR
    AS
      my_cursor_ref SYS_REFCURSOR;
    BEGIN
      OPEN my_cursor_ref FOR
           SELECT -- 150+ lines of query;
      RETURN my_cursor_ref;
    END;
    

    这是如何使用它:

    CREATE OR REPLACE PACKAGE BODY MyPackage
    as
    PROCEDURE PopulateTable
    IS 
      l_cur_refcur   SYS_REFCURSOR;
      s_array        fetch_array;
    BEGIN
      l_cur_refcur := my_ugly_query();
    
      LOOP
        FETCH tran_cursor BULK COLLECT INTO s_array;
        EXIT when s_array%NOTFOUND;
        FORALL counter in 1..s_array.COUNT
            INSERT INTO my_table VALUES s_array(counter);
      END LOOP;  
    
      CLOSE my_cursor;
      COMMIT;
    
    END PopulateTable;
    END MyPackage;
    
  • 2

    在包规范中创建游标而不是包体 . 然后,您可以使用package_name.cursor_name从任何包过程/函数中引用它

相关问题