4

次の例で、テーブルタイプのコレクションを他のテーブルと結合したい-

feed_logタイプのテーブルコレクションを返す関数F_GetPendingFeedsがあります。この戻ってきたコレクションをテーブルの1つと結合したい-

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

CREATE TYPEOracle 12Cより前は、サーバー上で作成されたコレクションからのみ選択できました。

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 に答える