Return 基于一个查询的游标的 2 个结果集(嵌套游标)
Return 2 resultset from cursor based on one query (nested cursor)
我正在尝试根据单个查询从存储过程中获取 2 个不同的结果集。我想做的是:
1.) return查询结果存入OUT游标;
2.) 从此游标结果中,获取每一列中所有最长的值,并且 return 作为第二个 OUT
结果集。
我试图避免用这个做同样的事情两次 - 获取数据,然后获取相同数据的最长列值。我不确定这是否可能,但如果可能,有人可以告诉我怎么做吗?
这是我想要做的一个例子(仅供说明):
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;
此示例使用“ORA-00942: table 或视图不存在”编译。
我知道这是一个愚蠢的例子,但我一直在调查和测试各种东西(隐式游标、获取游标、嵌套游标等),但没有发现任何对我有帮助的东西,特别是在使用存储的时候过程 returning 多个结果集。
我的总体目标是缩短 Excel 的数据导出时间。目前我必须 运行 两次相同的查询 - 一次计算数据大小以自动适应 Excel 列,然后将数据写入 Excel。
我相信操作第一个结果集以获得第二个结果集会更快 - 减少数据库周期。
我正在使用 Oracle 11g,非常感谢任何帮助。
游标中的每一行数据只能被读取一次;一旦从游标中读取了下一行(或一组行),则无法返回前一行(或一组行)并且无法重新使用游标。所以你问的是不可能的,就好像你读取游标来找到最大值一样(忽略你不能在 SELECT
语句中使用游标作为源但是,相反,你可以使用 PL/SQL 循环)那么游标的行将是 "used up" 并且游标关闭,因此当它从过程返回时无法读取。
您需要使用两个单独的查询:
CREATE 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)) AS max_name_length,
MAX(LENGTH(Surname)) AS max_surname_length
FROM MyTable;
END Test;
/
仅出于理论目的,如果您将数据批量收集到集合中,则可以仅从 table 中读取一次,然后从 table 集合表达式中读取 select(但是,code/maintain 会更复杂,并且需要将 table 中的行存储在内存中 [如果 table 很大,您的 DBA 可能不会欣赏] 并且可能不会比仅查询 table 两次更高效,因为您最终会得到三个 SELECT
语句而不是两个)。
类似于:
CREATE TYPE test_obj IS OBJECT(
name VARCHAR2(50),
surname VARCHAR2(50)
);
CREATE TYPE test_obj_table IS TABLE OF test_obj;
CREATE PROCEDURE MySchema.Test(
RESULT OUT SYS_REFCURSOR,
MAX_RESULT OUT SYS_REFCURSOR
)
AS
t_names test_obj_table;
BEGIN
SELECT Name,
Surname
BULK COLLECT INTO t_names
FROM MyTable;
OPEN RESULT FOR
SELECT * FROM TABLE( t_names );
OPEN MAX_RESULT FOR
SELECT MAX(LENGTH(Name)) AS max_name_length,
MAX(LENGTH(Surname)) AS max_surname_length
FROM TABLE( t_names );
END Test;
/
我正在尝试根据单个查询从存储过程中获取 2 个不同的结果集。我想做的是:
1.) return查询结果存入OUT游标;
2.) 从此游标结果中,获取每一列中所有最长的值,并且 return 作为第二个 OUT 结果集。
我试图避免用这个做同样的事情两次 - 获取数据,然后获取相同数据的最长列值。我不确定这是否可能,但如果可能,有人可以告诉我怎么做吗?
这是我想要做的一个例子(仅供说明):
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;
此示例使用“ORA-00942: table 或视图不存在”编译。
我知道这是一个愚蠢的例子,但我一直在调查和测试各种东西(隐式游标、获取游标、嵌套游标等),但没有发现任何对我有帮助的东西,特别是在使用存储的时候过程 returning 多个结果集。
我的总体目标是缩短 Excel 的数据导出时间。目前我必须 运行 两次相同的查询 - 一次计算数据大小以自动适应 Excel 列,然后将数据写入 Excel。
我相信操作第一个结果集以获得第二个结果集会更快 - 减少数据库周期。
我正在使用 Oracle 11g,非常感谢任何帮助。
游标中的每一行数据只能被读取一次;一旦从游标中读取了下一行(或一组行),则无法返回前一行(或一组行)并且无法重新使用游标。所以你问的是不可能的,就好像你读取游标来找到最大值一样(忽略你不能在 SELECT
语句中使用游标作为源但是,相反,你可以使用 PL/SQL 循环)那么游标的行将是 "used up" 并且游标关闭,因此当它从过程返回时无法读取。
您需要使用两个单独的查询:
CREATE 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)) AS max_name_length,
MAX(LENGTH(Surname)) AS max_surname_length
FROM MyTable;
END Test;
/
仅出于理论目的,如果您将数据批量收集到集合中,则可以仅从 table 中读取一次,然后从 table 集合表达式中读取 select(但是,code/maintain 会更复杂,并且需要将 table 中的行存储在内存中 [如果 table 很大,您的 DBA 可能不会欣赏] 并且可能不会比仅查询 table 两次更高效,因为您最终会得到三个 SELECT
语句而不是两个)。
类似于:
CREATE TYPE test_obj IS OBJECT(
name VARCHAR2(50),
surname VARCHAR2(50)
);
CREATE TYPE test_obj_table IS TABLE OF test_obj;
CREATE PROCEDURE MySchema.Test(
RESULT OUT SYS_REFCURSOR,
MAX_RESULT OUT SYS_REFCURSOR
)
AS
t_names test_obj_table;
BEGIN
SELECT Name,
Surname
BULK COLLECT INTO t_names
FROM MyTable;
OPEN RESULT FOR
SELECT * FROM TABLE( t_names );
OPEN MAX_RESULT FOR
SELECT MAX(LENGTH(Name)) AS max_name_length,
MAX(LENGTH(Surname)) AS max_surname_length
FROM TABLE( t_names );
END Test;
/