追加の観察として、ネストされたテーブル自体が大きすぎたり、メモリを使いすぎたりしているわけではありません。例外ハンドラーを使用すると、関数によってエラーがスローされていないことがわかります。匿名ブロックに同じものを入力できます。
DECLARE
ret_table nums_list := nums_list();
BEGIN
FOR i IN 1..4555555 LOOP
ret_table.EXTEND;
ret_table(i) := i;
END LOOP;
dbms_output.put_line(ret_table.count);
END;
/
anonymous block completed
4555555
また、ブロックから関数を呼び出すこともできます。
DECLARE
ret_table nums_list;
BEGIN
ret_table := generate_series(1,4555555);
dbms_output.put_line(ret_table.count);
END;
/
anonymous block completed
4555555
エラーが発生するのは、テーブル コレクション式として使用した場合のみです。
SQL Error: ORA-22813: operand value exceeds system limits
22813. 00000 - "operand value exceeds system limits"
*Cause: Object or Collection value was too large. The size of the value
might have exceeded 30k in a SORT context, or the size might be
too big for available memory.
*Action: Choose another value and retry the operation.
原因テキストはSORT コンテキストを参照しており、クエリによって並べ替えが行われています。
------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 2 | 29 (0)| 00:00:01 |
| 1 | SORT AGGREGATE | | 1 | 2 | | |
| 2 | COLLECTION ITERATOR PICKLER FETCH| GENERATE_SERIES | 8168 | 16336 | 29 (0)| 00:00:01 |
------------------------------------------------------------------------------------------------------
@a_horse_with_no_name が示唆したように、関数をパイプライン化することで問題を回避できます。
CREATE OR REPLACE FUNCTION generate_series(from_n NUMBER, to_n NUMBER)
RETURN nums_list PIPELINED AS
BEGIN
FOR i IN from_n..to_n LOOP
PIPE ROW (i);
END LOOP;
RETURN;
END;
/
SELECT count(*) FROM TABLE ( generate_series(1,4555555) );
COUNT(*)
----------
4555555
それでも問題はありSORT AGGREGATE
ませんが、もう気にしないようです。どちらの場合もなぜそうするのかよくわかりません。おそらく他の誰かがそれが何をしているのか説明できるでしょう。(ちなみに、11gR2 インスタンスでこれを行っています。動作が同じであることを確認するための 12c インスタンスはありませんが、症状はそうであることを示唆しています)。または、問題は SORT コンテキストではなく、使用可能なメモリである可能性があります。私の環境では、あなたのバージョンは最大 4177918 要素まで一貫して動作しているようです。これは重要な数ではないようで、環境に関連している可能性がありますか?
ただし、コレクションをどのように使用するかによって異なります。PL/SQL コンテキストからは、元のバージョンの方が適している可能性があります。