sql >> データベース >  >> RDS >> Oracle

再帰的サブクエリファクタリングによる循環検出

    CONNECT_BY_ISCYCLEのドキュメントから :

    CONNECT_BY_ISCYCLE pseudocolumnは1を返します 現在の行にその祖先でもある子がある場合

    CYCLEのそれ :

    祖先の行の1つがサイクル列に対して同じ値を持っている場合、その行はサイクルを形成していると見なされます。

    あなたの例では、行2 祖先でもある子がありますが、そのid まだ返送されていません。

    つまり、CONNECT_BY_ISCYCLE 子供をチェックします (まだ返されていません)、CYCLE 現在の行をチェックします (これはすでに返されています)。

    CONNECT BY 行ベースですが、再帰的なCTE はセットベースです。

    CYCLEに関するOracleのドキュメントに注意してください。 「祖先の行」について言及しています。ただし、一般的に言えば、再帰的なCTEには「祖先行」の概念はありません。 。これはセットベースの操作であり、ツリーから完全に結果を得ることができます。一般的に、アンカー部分と再帰部分は異なるテーブルを使用することもできます。

    再帰的なCTE以降 は通常 階層ツリーの構築に使用、Oracle サイクルチェックを追加することにしました。ただし、セットベースの方法により、再帰的なCTE の動作では、「祖先行」のサイクル条件も明確に定義できないため、次のステップでサイクルが生成されるかどうかを判断することは一般に不可能です。

    「次の」ステップを実行するには、「現在の」セット全体が使用可能である必要がありますが、現在のセットの各行(サイクル列を含む)を生成するには、「次の」操作の結果が必要です。

    現在のセットが常に単一の行で構成されている場合(CONNECT BYのように)、問題はありません。 )が、セット全体で再帰演算が定義されている場合は問題になります。

    Oracle 11を調べていません まだですが、SQL Server 再帰的なCTEを実装します CONNECT BYを非表示にするだけです その背後には、多数の制限を設ける必要があります(これらはすべて、セットベースのすべての操作を効果的に禁止します)。

    PostgreSQL 一方、の実装は真にセットベースです。再帰部分のアンカー部分を使用して任意の操作を実行できます。ただし、サイクルはそもそも定義されていないため、サイクルを検出する手段はありません。

    前に述べたように、MySQL CTEを実装していません はまったくありません(HASH JOINは実装されていません またはMERGE JOIN ■同様に、ネストされたループのみなので、それほど驚かないでください。

    皮肉なことに、私は今日、このテーマに関する手紙を受け取りました。これについてはブログで取り上げます。

    更新:

    再帰的なCTE SQL ServerCONNECT BYにすぎません 変装した。衝撃的な詳細については、私のブログのこの記事を参照してください:

    • SQL Server:再帰CTEは本当にセットベースですか?


    1. SQLServerの複数の列に外部キー制約を作成する方法-SQLServer/TSQLチュートリアルパート67

    2. SQLServerの既存のSQLServerテーブルから新しいテーブルをバックアップまたは作成する方法-SQLServer/TSQLチュートリアルパート105

    3. MariaDB JSON_VALUE()の説明

    4. MySQL空間拡張を使用して、円内のポイントを選択します