Stored procedures 基于一个查询从游标返回2个结果集(嵌套游标)

Stored procedures 基于一个查询从游标返回2个结果集(嵌套游标),stored-procedures,oracle11g,database-cursor,Stored Procedures,Oracle11g,Database Cursor,我试图基于一个查询从存储过程中获得两个不同的结果集。我想做的是: 1.)将查询结果返回到OUT游标中 2.)从光标结果中,获取每列中的所有最长值,并将其作为第二个输出返回 结果集 我试图避免对这个做两次同样的事情——获取数据,然后获取相同数据的最长列值。我不确定这是否可能,但如果可能,有人能告诉我怎么做吗 这是我想做的一个例子(仅用于说明): 此示例使用“ORA-00942:表或视图不存在”编译 我知道这是一个愚蠢的例子,但我一直在调查和测试各种各样的东西(隐式游标、获取游标、嵌套游标等),没有

我试图基于一个查询从存储过程中获得两个不同的结果集。我想做的是:

1.)将查询结果返回到OUT游标中

2.)从光标结果中,获取每列中的所有最长值,并将其作为第二个输出返回 结果集

我试图避免对这个做两次同样的事情——获取数据,然后获取相同数据的最长列值。我不确定这是否可能,但如果可能,有人能告诉我怎么做吗

这是我想做的一个例子(仅用于说明):

此示例使用“ORA-00942:表或视图不存在”编译

我知道这是一个愚蠢的例子,但我一直在调查和测试各种各样的东西(隐式游标、获取游标、嵌套游标等),没有发现任何对我有帮助的东西,特别是在处理返回多个结果集的存储过程时

我的总体目标是缩短Excel的数据导出时间。目前,我必须运行两次相同的查询—一次用于计算数据大小以自动调整Excel列,然后用于将数据写入Excel

我相信,为了得到第二个结果集而操纵第一个结果集会快得多——只需要更少的DB周期


我使用的是Oracle 11g,非常感谢您的帮助。

游标中的每一行数据都可以准确读取一次;从光标读取下一行(或一组行)后,上一行(或一组行)将无法返回到,且光标无法重复使用。因此,您所要求的是不可能的,因为如果您读取光标以查找最大值(忽略您不能在
SELECT
语句中使用光标作为源,而是可以使用PL/SQL循环来读取它),那么光标的行将“用完”并且游标关闭,因此从过程返回时无法读取

您需要使用两个单独的查询:

创建过程MySchema.Test(
结果输出系统参考光标,
最大结果输出系统参考光标
)
作为
开始
公开结果
选择名称,
姓
从MyTable;
打开的最大结果为
选择MAX(LENGTH(Name))作为MAX_Name_LENGTH,
MAX(长度(姓氏))作为MAX_姓氏长度
从MyTable;
结束试验;
/
仅出于理论目的,如果将数据批量收集到集合中,然后从表集合表达式中进行选择,则只能从表中读取一次(但是,编码/维护将更加复杂,并且需要将表中的行存储在内存中)[如果表很大,您的DBA可能不喜欢这一点]并且可能不会比只查询两次表更有效,因为您将得到三条
SELECT
语句,而不是两条)

比如:

CREATE TYPE test_obj是对象(
名称VARCHAR2(50),
姓氏VARCHAR2(50)
);
创建型式试验对象表是试验对象表;
创建过程MySchema.Test(
结果输出系统参考光标,
最大结果输出系统参考光标
)
作为
测试对象表的名称;
开始
选择名称,
姓
批量收集到t_名称中
从MyTable;
公开结果
从表中选择*(t_名称);
打开的最大结果为
选择MAX(LENGTH(Name))作为MAX_Name_LENGTH,
MAX(长度(姓氏))作为MAX_姓氏长度
来自表(t_名称);
结束试验;
/

一个游标中的每一行数据都可以精确读取一次;一旦从游标中读取下一行(或一组行),则无法返回上一行(或一组行),并且无法重复使用游标。因此,您所要求的是不可能的,就像您读取游标以找到最大值一样(忽略不能在
SELECT
语句中使用游标作为源,但可以使用PL/SQL循环读取它)然后游标的行将被“用完”,并且游标关闭,因此从过程返回时无法读取

您需要使用两个单独的查询:

创建过程MySchema.Test(
结果输出系统参考光标,
最大结果输出系统参考光标
)
作为
开始
公开结果
选择名称,
姓
从MyTable;
打开的最大结果为
选择MAX(LENGTH(Name))作为MAX_Name_LENGTH,
MAX(长度(姓氏))作为MAX_姓氏长度
从MyTable;
结束试验;
/
仅出于理论目的,如果将数据批量收集到集合中,然后从表集合表达式中进行选择,则只能从表中读取一次(但是,编码/维护将更加复杂,并且需要将表中的行存储在内存中)[如果表很大,您的DBA可能不喜欢这一点]并且可能不会比只查询两次表更有效,因为您将得到三条
SELECT
语句,而不是两条)

比如:

CREATE TYPE test_obj是对象(
名称VARCHAR2(50),
姓氏VARCHAR2(50)
);
创建型式试验对象表是试验对象表;
创建过程MySchema.Test(
结果输出系统参考光标,
最大结果输出系统参考光标
)
作为
测试对象表的名称;
开始
选择名称,
姓
批量收集到t_名称中
从MyTable;
公开结果
从表中选择*(t_名称);
打开的最大结果为
选择MAX(LENGTH(Name))作为MAX_Name_LENGTH,
MAX(长度(姓氏))作为MAX_姓氏长度
来自表(t_名称);
结束试验;
/

@MTO,一个完美的答案,谢谢你。我祈祷有人能理解我想要什么,你就把它钉死了。不幸的是,你证实了我的怀疑,所以我对答案也不太满意:)@MTO,关于第一个建议-两个查询-我知道我可以做到这一点,但我的过程中的查询相当长,所以编写两个而不是一个…好吧,代码将
CREATE OR REPLACE PROCEDURE MySchema.Test(RESULT OUT SYS_REFCURSOR,MAX_RESULT OUT SYS_REFCURSOR)
AS

BEGIN

 OPEN RESULT FOR SELECT Name,Surname FROM MyTable; 

 OPEN MAX_RESULT FOR SELECT Max(length(Name)),Max(length(Surname)) FROM RESULT; --error here 

END Test;