4

我想在以下示例中将表类型的集合与其他表连接起来 -

我有一个函数 F_GetPendingFeeds,它返回 feed_log 类型的表集合。我想将这个返回的集合与其中一张表一起加入 -

CREATE OR REPLACE PACKAGE BODY L_DemoPkg
IS
   TYPE t_feedLog IS TABLE OF feed_log%ROWTYPE
                INDEX BY PLS_INTEGER;

   FUNCTION F_GetPendingFeeds
      RETURN t_feedLog
   IS
   lo_feedLog t_feedLog;
   BEGIN
      SELECT feed_log_seq
         , processed_dt
         , processed_by
         , create_dt
         , created_by
      BULK COLLECT INTO lo_feedLog
      FROM feed_log
      WHERE status_cd = 0;

      RETURN lo_feedLog;

   EXCEPTION
      WHEN OTHERS THEN
         --TODO: Log Exception
         RAISE;
   END F_GetPendingFeeds;


   PROCEDURE P_ProcessFeed
   IS
   o_pendingFeed t_feedLog;
   ln_totalRecords t_feedLog;

   BEGIN

      -- Get the list of pending feed ids
      o_pendingFeed := F_GetPendingFeeds();

      -- Check if new data is present for processing
      IF o_pendingFeed.COUNT = 0 THEN
         dbms_output.put_line('Feed processing failed. No data found.');
         RETURN;
      END IF;

      SELECT COUNT(*)
      INTO ln_totalRecords
      FROM  feed_details t1
          , table(o_pendingFeed) t2 --ERROR: ORA-22905: cannot access rows from a non-nested table item
      WHERE t1.feed_log_seq = t2.feed_log_seq;

   EXCEPTION
      WHEN OTHERS THEN
         --TODO: Log Exception
         RAISE;
   END P_ProcessFeed;
END;

我收到错误 -

PL/SQL: SQL Statement ignored
PL/SQL: ORA-22905: cannot access rows from a non-nested table
     item

请注意,我想将集合与表一起加入 -

  FROM  feed_details t1
      , table(o_pendingFeed) t2 --ERROR: ORA-22905: cannot access rows from a non-nested table item   WHERE t1.feed_log_seq = t2.feed_log_seq;
4

2 回答 2

7

在 Oracle 12C 之前,您只能从使用CREATE TYPE例如在服务器上创建的集合中进行选择

SQL> CREATE TYPE r_feedLog IS OBJECT (foo NUMBER, bar VARCHAR2(20));
SQL> CREATE TYPE t_feedLog IS TABLE OF r_feedLog;

然后t_feedLog从你的包中删除声明。

使用 Oracle 12C,可以从包规范中定义的 PL/SQL 表中进行选择。

于 2013-01-29T13:52:12.963 回答
5

你这里有几个错误。首先,要访问强制转换中的数组,TABLE您需要使用 SQL 数组(好吧,您仍然可以使用 PL/SQL 表,但这仅适用于流水线函数,因为 Oracle 将为您静默创建 SQL 类型;但是即使在那种情况下,使用 SQL 数组仍然更整洁)。所以你需要这样做:

SQL> create type r_feedlog is object
  2  (
  3    feed_log_seq number,
  4     processed_dt date,
  5    processed_by varchar2(10),
  6    create_dt date,
  7    created_by varchar2(10)
  8  );
  9  /

Type created.

SQL> create type t_feedLog as table of r_feedlog;
  2  /

Type created.

然后使用它而不是 pl/sql 索引表。其次

   ln_totalRecords t_feedLog;

应该是一个数字而不是一个集合,因为您选择 count(*) 。还 :

  BULK COLLECT INTO lo_transferFeedDef

应该

  BULK COLLECT INTO lo_feedLog 

你当然可以拥有流水线的功能,例如:

CREATE OR REPLACE PACKAGE L_DemoPkg
as
  type r_feedlog is record(feed_log_seq number,
                           processed_dt date,
                           processed_by varchar2(10),
                           create_dt date,
                           created_by varchar2(10));
  type t_feedLog is table of r_feedlog;

  function F_GetPendingFeeds return t_feedLog pipelined;

  procedure P_ProcessFeed;
end;
/

并在包体内:

FUNCTION F_GetPendingFeeds
   RETURN t_feedLog pipelined
IS
lo_feedLog r_feedlog;
BEGIN
   for r_row in (SELECT feed_log_seq
                        , processed_dt
                        , processed_by
                        , create_dt
                        , created_by
                   FROM feed_log
                  WHERE status_cd = 0)
   loop
     lo_feedLog.feed_log_seq := r_row.feed_log_seq;
     lo_feedLog.processed_dt := r_row.processed_dt;
     lo_feedLog.processed_by := r_row.processed_by;
     lo_feedLog.create_dt := r_row.create_dt;
     lo_feedLog.created_by := r_row.created_by;
     pipe row(lo_feedLog);
   end loop;
END F_GetPendingFeeds;

在此过程中,您可以:

SELECT COUNT(*)
INTO ln_totalRecords
FROM  feed_details t1
    , table(F_GetPendingFeeds()) t2
WHERE t1.feed_log_seq = t2.feed_log_seq;

以上是保留一个 pl/sql 数组。如果你有 SQL 数组,函数会更紧凑:

FUNCTION F_GetPendingFeeds
   RETURN t_feedLog pipelined
IS
BEGIN
   for r_row in (SELECT r_feedlog(feed_log_seq
                        , processed_dt
                        , processed_by
                        , create_dt
                        , created_by) data
                   FROM feed_log
                  WHERE status_cd = 0)
   loop
     pipe row(r_row.data);
   end loop;
END F_GetPendingFeeds;
于 2013-01-29T13:52:10.513 回答