我想在游标上运行一些代码,但也报告光标的内容,这样我就可以预览它将要做什么。预览是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。
我不清楚为什么你需要第二个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);