我希望在游标上运行一些代码,但也要报告游标的内容,以便我可以预览它将要执行的操作。预览是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;
/
对于我的预览,我想给最终用户一个简单的表,过滤他们可以刷新的排序。在不重复查询的情况下,使用一个简单的Excel查询表,其中包含一个返回REF CURSOR
的过程。 {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。
答案 0 :(得分: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);