如何将用户定义的表类型传递给游标作为参数?

时间:2018-08-08 15:43:43

标签: oracle plsql

我试图将包定义的表类型作为参数输入到游标中,并将其作为表连接,但是显然,它与使用数据库定义的表类型不同。以下示例适用于数据库定义的表类型。

以以下包主体为例:

CREATE OR REPLACE PACKAGE BODY MY_PACK AS
/*******************
    TYPES
********************/
TYPE A_TYPE IS RECORD(
    ID          NUMBER(20),
    CHECK_DATE  DATE
);
TYPE A_TABLE_TYPE IS TABLE OF TYPE A_TYPE BY VARCHAR2(2000);

CURSOR CUR1... -- Does what it does.

CURSOR CUR2(C_TABLE A_TABLE_TYPE)
IS
-- PROBLEM **************************************
  SELECT * 
  FROM TABLE(C_TABLE);

PROCEDURE PROC1 (....)
IS
  l_table      A_TABLE_TYPE;
  l_rec        A_TYPE;
BEGIN
    FOR RES IN CUR1(...)
    LOOP
        IF NOT l_table.EXISTS(RES.ID) THEN
            l_rec.ID := RES.ID;
            l_rec.CHECK_DATE := RES.DATE;
            l_table(RES.ID) := l_rec;
        END IF;
    END LOOP;

    -- ************** PROBLEM ****************************************
    FOR RES2 IN CUR2(C_TABLE => l_table)
    LOOP
        -- DOO
    END LOOP;
END PROC1;

评论示例:

CURSOR CUR2(C_TABLE A_TABLE_TYPE) 
IS
  SELECT *
  FROM
    (SELECT ID FROM TABLE(C_TABLE) ) AS FILTER,
    DB_TABLE
  WHERE DB_TABLE.ID = FILTER.ID;

1 个答案:

答案 0 :(得分:1)

以下是一些建议:

替代1: 您可以尝试在循环中使用显式光标

for rec in (SELECT *
              FROM
                (SELECT ID FROM TABLE(l_table) ) AS FILTER,
                DB_TABLE
              WHERE DB_TABLE.ID = FILTER.ID
           )
loop
...
end loop;

替代2:

您可以通过将cur1中的select与cur2中的select结合起来来做1游标

替代3:

建议不要使用包中的记录,而应使用Oralce类型。 您创建一个对象类型和一个表类型

create or replace type a_type as object 
( 
    ID          NUMBER(20),
    CHECK_DATE  DATE

)
/

CREATE OR REPLACE TYPE a_type_tab IS TABLE OF a_type ;
/

然后您可以在光标中将此类型用作参数

CURSOR CUR2(t a_type_tab)
IS
  SELECT * 
  FROM TABLE(t);

在此过程中,您可以轻松填充此类型并将其传递给光标

procedure test as

    tab a_type_tab;
  begin
    tab := a_type_tab();
    for rec in cur1 loop

      tab.EXTEND();
      tab(tab.last) := a_type(rec.id,rec.dat);

    end loop;

    for rec2 in cur2(tab) loop
       dbms_output.put_line(rec2.id);
    end loop;
  end test;