将显式游标转换为引用游标而不重命名列ATTR_n

问题描述 投票:0回答:1

我想在游标上运行一些代码,但也报告光标的内容,这样我就可以预览它将要做什么。预览是Excel中的查询表,并希望REF CURSOR用于{Call}语法。在PL / SQL中,编码的自然语法是显式游标。在this question的@XING的帮助下,我开发了这个软件包。

CREATE OR REPLACE PACKAGE MyPackage
AS

  -- This could be a complex query with many paramters and columns
  CURSOR curMyCursor(pParam1 VARCHAR2) IS
  SELECT pParam1 hello, 'ColNames' goodbye
  FROM DUAL;

  -- I could just let GiveMyCursor return a SYS_REFCURSOR but wanted to try max clues
  TYPE refMyCursor IS REF CURSOR RETURN curMyCursor%ROWTYPE;
  -- The TABLE function in GiveMyCursor needs the row type to be externalized
  TYPE typMyCursor IS TABLE OF curMyCursor%ROWTYPE;

  PROCEDURE RunMyCursor(pParam1 IN VARCHAR2);
  PROCEDURE GiveMyCursor(pCursor OUT refMyCursor, pParam1 IN VARCHAR2);

END MyPackage;
/

CREATE OR REPLACE PACKAGE BODY MyPackage
AS

  PROCEDURE RunMyCursor(pParam1 IN VARCHAR2) IS
  BEGIN
    FOR recMyCursor IN curMyCursor(pParam1) LOOP
      NULL; -- Do normal cursor loop processing
    END LOOP;
  END RunMyCursor;

  PROCEDURE GiveMyCursor(pCursor OUT refMyCursor, pParam1 IN VARCHAR2) IS
    tabMyCursor typMyCursor;
  BEGIN
    OPEN curMyCursor(pParam1);
    -- Load the entire contents of the cursor into memory and pray it fits
    FETCH curMyCursor BULK COLLECT INTO tabMyCursor;  
    CLOSE curMyCursor;

    -- PROBLEM: The TABLE function renames the columns ATTR_1, ATTR_2, etc
    OPEN pCursor FOR 
    SELECT ATTR_1 HELLO, ATTR_2 GOODBYE 
    FROM TABLE(tabMyCursor);
  END GiveMyCursor;

END MyPackage;
/

对于我的预览,我想给最终用户一个简单的表,过滤他们可以刷新的排序。在不重复查询的情况下,使用一个返回REF CURSOR的过程的简单Excel查询表,例如{call MyPackage.GiveMyCursor('World')}给出:

HELLO | GOODBYE
------+---------
World | ColNames

如果我没有在OPEN pCursor中重新指定列名,我会得到

ATTR_1| ATTR_2
------+---------
World | ColNames

所以OPEN pCursor FOR SELECT *允许我增强/修复我的查询而没有其他维护分支,但最终用户将丢失列描述。

在GiveMyCursor中是否有某种方法我可以添加一些代码以防止必须重新指定所有列名。一些内置的DBMS包我可以对游标或其中一种类型进行整理以构建一个字符串或某些内容以使其保持通用?

我的数据库是Oracle 12.1.0.1 SE。

oracle plsql
1个回答
2
投票

我不清楚为什么你需要第二个REF CURSOR作为OUT参数,当curMyCursor本身可以通过。

在你的代码评论中,

- 将光标的全部内容加载到内存中并祈祷它适合

您是否可能假设将记录存储在内存中会产生更好的性能?事实上,当您使用CURSOR时,Oracle实际上会打开一个存储处理信息的未命名工作区。那么,为什么不直接传递第一个CURSOR并在调用块中使用它?

话虽如此,在你的情况下,声明

FETCH curMyCursor BULK COLLECT INTO tabMyCursor

不会执行列到列的映射,除非您在声明集合时已正确定义它。

你可以做的是,用预期的列数据类型声明一个RECORD

 TYPE MyrecordType is RECORD 
(
 hello VARCHAR2(10),
 goodbye VARCHAR2(10)
 );
TYPE typMyCursor IS TABLE OF MyrecordType ;

代替

TYPE typMyCursor IS TABLE OF curMyCursor%ROWTYPE;

现在,您将拥有集合中记录元素的所有列的专有名称。然后,您应该能够直接使用SELECT *而不是指定元素。

OPEN pCursor FOR 
    SELECT *
    FROM TABLE(tabMyCursor);
© www.soinside.com 2019 - 2024. All rights reserved.