処理中の基礎となるデータに循環が存在すると、再帰ビューは永久に再帰する可能性があります。循環しないデータがある場合も同様です。非循環データによる永久再帰処理を回避を参照してください。たとえば、輸送システムで取られるさまざまなルートが存在し得ます。そのような循環が部品テーブルの問題に現れる可能性は極めて低いですが、この問題を図示するために以下に例を示します。
例えば、以下のpartsテーブルがあるとします。
部品 | ||
---|---|---|
メジャー | マイナー | 数量 |
p1 | P2 | 2 |
p1 | p3 | 3 |
p1 | p4 | 2 |
P2 | p3 | 3 |
p3 | p5 | 2 |
p3 | p1 | 3 |
p4 | P2 | 4 |
このテーブルのデータを処理するために再帰的ビューを作成するので、次の再帰的ビュー定義を作成します。
CREATE RECURSIVE VIEW px (major, minor) AS ( SELECT major, minor FROM parts WHERE major = 'p1' UNION ALL SELECT px.major, parts.minor FROM px, parts WHERE parts.major = px.minor);
次に、ここで定義した再帰的ビューpxに対して以下のSELECTリクエストを実行します。
SELECT major, minor FROM px;
- 部品p3はマイナー、または子構成要素として部品p1を持ちます。
- 部品p4は子構成要素として部品p2を持ちます。
- 部品p2は子構成要素として部品p3を持ちます。
- 最初の箇条書きリストで示しているように、部品p3も子構成要素として部品p1を持ちます。
シンボリックに提示すると、循環は次のようにより簡単に視覚化できるかもしれません。
p1 p2 p3 p1 p2 p3(以下同様)。
同様に、2番目の循環も次のように視覚化できます。
p1 p4 p2 p3 p1 p4 p2(以下同様)。
階層図は次のようになります。
次の情報定義を考えます。
グラフの種類 | 説明 |
---|---|
循環 | その1つ以上のノードは直接的または間接的に自分自身にデータを送り返す。 |
非循環 | そのノードは自分自身にデータを送り返さない。 |
永久再帰処理の可能性があるのは循環グラフだけで、非循環グラフは定義によって永久に再帰することはありません。
この例ではノードの p3 ノードの p1 に戻って及びノード p4 飼料ノード p1 に戻ってグラフが循環するので、ノード p2 と p3 を調べることによって。
これらの間の循環関係により永久再帰処理が発生し、停止しないとクエリーはスプールのオーバーフローを無視して永久にループします。再帰処理の概念を振り返ると、この再帰の不動点は次のとおりです。
それでは、ランナウェイ永久再帰処理が起こらないようにするにはどうしたらよいでしょうか。結局、基本テーブル データ内の循環を判別しようとすると、多大の労力が必要であるにもかかわらず、メリットはあまりありません。
1つの方法として、例の中の再帰的ビュー px に関する定義を次のように変更することもできます。
CREATE RECURSIVE VIEW px (major, minor, mycount) AS ( SELECT major, minor, 0 AS mycount FROM parts WHERE major = 'p1' UNION ALL SELECT px.major, parts.minor, px.mycount + 1 FROM px, parts WHERE parts.major = px.minor AND px.mycount <= 40);
ANDで付加されている条件px.mycount <= 40により、再帰処理の循環が41以下に限定されます。条件はpx.mycountに対して適用され、これは1ではなく0に初期設定されるため、41となります。
必須ではありませんが、プログラミングの慣例上、再帰処理の深さを限定する再帰的ビュー定義の再帰的クエリーの部分に常に制約を指定するのは望ましいことです。
- シード クエリー内の各SELECTリクエストのカウンタを定数値に初期化します。ほとんどのアプリケーションでは、定数値を0に初期化します。
- カウンタが1ずつ増加するように再帰的クエリー内の各SELECTリクエストをコーディングします。
- カウンタの値をテストする条件を指定するように再帰的クエリー内の各SELECTリクエストをコーディングします。このテスト条件の形式は次のいずれかになります。
- counter < condition
- counter ≤ condition
conditionの値は、プロトタイピングまたは見積もりによって判別される値になります。一般に、試験なしで最適条件を判別することはできません。
限定条件がないと、ランナウェイ再帰処理は、再帰ビューに対してクエリーを実行するユーザーに指定されるスプール領域の量によってのみ限定されます(ユーザーにスプール領域を割り当てる方法については、CREATE USERを参照)。限定条件を指定してもユーザーに割り当てられる最大スプール領域の量は除去されないため、条件に対してあまりにも大きな値を指定すると、その条件によって指定された最終値に到達することなくそのスプールの最大値をオーバーフローする可能性があります。