如何从oracle PL / SQL集合中选择所有行到SYS_REFCURSOR

时间:2018-05-22 20:49:27

标签: sql oracle plsql

注意:我已经看到很多解决方案,所有人都说我不能使用带有PL / SQL类型的SQL。我必须使用CREATE或REPLACE,但我的限制是我无法使用系统对象执行此任务。

我在下面的例子中尝试过的只返回最后一行。

create or replace PROCEDURE SP_TEST (TEST_cursor OUT SYS_REFCURSOR)IS
 TYPE TEMP_RECORD IS RECORD(
                    entries   NUMBER,
                    name      VARCHAR2(50),
                    update    VARCHAR2(200)
                );
TYPE TEMP_TABLE IS TABLE OF TEMP_RECORD INDEX BY PLS_INTEGER;
VAR_TEMP       TEMP_TABLE;
IDX            PLS_INTEGER := 0;
BEGIN 
VAR_TEMP(IDX).cur_entries := 1;
VAR_TEMP(IDX).cur_entries := 2;
 OPEN TEST_cursor FOR
 SELECT VAR_TEMP(idx).cur_entries from dual;
END SP_TEST;

尝试了另一种方法。

OPEN TEST_cursor FOR
  SELECT * FROM TABLE(VAR_TEMP)
--- It gives compilation error ora-

2 个答案:

答案 0 :(得分:1)

鉴于您无法在数据库中创建对象,我能想到的唯一解决方案是使用动态SQL:

CREATE TYPE temp_record AS OBJECT
(
    entries NUMBER,
    entry_name VARCHAR2 (50),
    update_value VARCHAR2 (200)
);

CREATE TYPE temp_table IS TABLE OF temp_record;

CREATE OR REPLACE PROCEDURE sp_test (test_cursor OUT SYS_REFCURSOR) IS
    var_temp temp_table := temp_table ();
    strSql  VARCHAR2(32767);
BEGIN
    -- Populate the temp table, or pass it in from elsewhere

    var_temp.EXTEND();
    var_temp (var_temp.LAST).entries := 1;
    var_temp (var_temp.LAST).entry_name := 'test';

    FOR i IN 1..var_temp.COUNT LOOP
      strSql := strSql ||
                  CASE
                    WHEN LENGTH(strSql) > 0 THEN ' UNION ALL '
                    ELSE NULL
                  END ||
                  'SELECT ' || var_temp.ENTRIES || ' ENTRIES,' ||
                            '''' || var_temp.ENTRY_NAME || ''' ENTRY_NAME FROM DUAL';
    END LOOP;

    OPEN test_cursor FOR strSql;
END sp_test;

现在,我可能已经把字符串连接逻辑弄乱了一点,但目标是最终得到一个类似于

的SQL字符串。
SELECT 1 ENTRIES,'test' ENTRY_NAME FROM DUAL
UNION ALL
SELECT 2 ENTRIES,'test 2' ENTRY_NAME FROM DUAL
UNION ALL
SELECT 3 ENTRIES,'test_3' ENTRY_NAME FROM DUAL

但是,当然,没有漂亮的空白等等。

动态SQL的32K限制可能最终会让你感到困惑,但是如果推动推动你可以使用DBMS_SQL包处理任意大的SQL文本,尽管这会带来挑战。

祝你好运。

答案 1 :(得分:0)

为了引用SQL中的类型(而不是PL / SQL),必须将它们创建为数据库中的对象。这实际上是一个范围问题:当您运行SQL时,您将转移到不同的上下文。您在本地创建的任何结构都不可用。

CREATE TYPE temp_record AS OBJECT
(
    entries NUMBER,
    entry_name VARCHAR2 (50),
    update_value VARCHAR2 (200)
);

CREATE TYPE temp_table IS TABLE OF temp_record;

CREATE OR REPLACE PROCEDURE sp_test (test_cursor OUT SYS_REFCURSOR) IS
    var_temp temp_table := temp_table ();
BEGIN
    var_temp.EXTEND ();
    var_temp (var_temp.LAST).entries := 1;
    var_temp (var_temp.LAST).entry_name := 'test';

    OPEN test_cursor FOR SELECT * FROM TABLE (var_temp);
END sp_test;