You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: Patterns Recursive CTEs.md
+12-6Lines changed: 12 additions & 6 deletions
Original file line number
Diff line number
Diff line change
@@ -6,17 +6,23 @@ parent: Design Patterns
6
6
permalink: /patterns/rec-cte
7
7
---
8
8
9
-
Because, by design, SQL delegates the flow control of statement evaluation to the database engine, the standard SQL grammar does not include any flow control structures. The only exception is expression-level branching control. This control structure has operator and function representation, which is why it naturally integrates within an expression. Adding statement-level flow controls, such as branching or loops, necessitates grammar extension or special conventions. Recursive CTEs (RCTEs) follow the latter approach and implement the while/repeat loop structure. A general loop structure has four essential components: initialization code, the body of the loop, syntactic elements marking the beginning and end of the body code, and a means to exit the loop (termination conditions).
10
-
11
-
RCTEs do not introduce any special grammar/syntax; instead, it uses the standard SELECT statement syntax and a special convention. The result is quite contrived; for this reason, comprehending and mastering RCTEs may not be straightforward. Because the sole function of SQL is the construction and manipulation of row sets (views), the initialization and loop body blocks of an RCTE constitute complete SELECT statements. The initialization query generates starting view used as one of the sources by the body query. Each execution cycle of the loop body yields a new view used as one of the sources by the following loop cycle. There are two possible termination conditions. If the loop body includes the LIMIT clause, the loop terminates after the specified number of rows is processed. Alternatively, the loop terminates after processing all previously returned rows, with the loop body returning empty row sets.
9
+
By design, SQL delegates statement-level flow control to the database engine, so the standard SQL grammar does not include any flow control structures. The only exception is expression-level branching control. This control structure has operator and function representations, so it naturally integrates within an expression (similar to other functions/operators). Adding statement-level flow controls, such as branching or loops, necessitates grammar extension or special conventions. Recursive CTEs (RCTEs) follow the latter approach and implement the while/repeat loop structure without special grammar/syntax. The result is quite contrived; thus, comprehending and mastering RCTEs may not be straightforward.
12
10
13
-
By convention, initialization and loop body SELECT blocks should be part of the same CTE. Because a CTE is, in turn, a SELECT statement, a set operator (such as UNION) must glue the initialization and loop body blocks, yielding a compound SELECT. Naturally, the initialization block goes first, followed by the body. The body query, by convention, uses its CTE name as one of the sources in the FROM clause. The CTE may include multiple set operations, and the first SELECT block referencing its CTE's name constitutes marks the beginning of the body block, with all preceding code forming the initialization query.
11
+
A general loop structure has two essential code blocks - initialization and loop body. Conventionally, the RCTE analogous blocks must fit within a single WITH clause member block. Because the latter only supports SELECT-type members, an RCTE must also represent a valid SELECT statement. At the same time, RCTEs, like SQL in general, focus on row sets/views manipulation. The idea is that the initialization query generates a starting view used as one of the sources by the first loop cycle. Each execution of the loop body yields a new view used as one of the sources by the following loop cycle. Accordingly, both code blocks must represent complete SELECT statements. And because the two SELECT blocks must form a valid SELECT query, they should be glued together via a set operator, such as UNION.
14
12
15
-
The resulting view of an RCTE query is the compound consisting of the row set produced by the initialization query combined with all row sets returned by individual loop cycles using the specified set operator (the operator separating the initialization and the body blocks).
13
+
By convention, the resulting view of an RCTE query is the compound consisting of the row set produced by the initialization query combined with all row sets returned by individual loop cycles using the specified set operator (the operator separating the initialization and the body blocks). This convention permits, for example, retrieving a subtree from a hierarchy modeled with the parent reference pattern.
16
14
17
-
Yet another convention is related to the meaning of the RCTE name. Outside the RCTE, its name refers to the resulting view above. This meaning is the same for both ordinary and recursive CTEs. An ordinary CTE cannot use its name as one of its sources. Within an RCTE, on the other hand, its name refers to the processing frame/view, which, to a first approximation, contains the row set returned by the previous cycle or the initialization query for the first cycle. More precisely, the processing frame is a single row view (in a sense, a pointer to the next exiting row of the processing queue) sitting at the tip of a dynamically generated processing queue, as discussed later.
15
+
Yet another convention is related to the meaning of the RCTE name. Outside the RCTE, its name refers to the resulting view above. This meaning is the same for both ordinary and recursive CTEs. An ordinary CTE cannot use its name as one of its sources. An RCTE, on the other hand, must use its name. Within an RCTE, its name refers to the processing frame/view, which, to a first approximation, contains the row set returned by the previous cycle or the initialization query for the first cycle. In other words, the inner and outer references to the RCTE name mean two completely different things.
16
+
17
+
Another essential feature of a loop structure is loop body start/end markers. By convention, the RCTE loop body starts with the first SELECT query portion that uses the RCTE name as one of its sources. The loop body must incorporate all code through the end of the RCTE code block, with all preceding code forming the initialization query. The body part may be a compound SELECT query combined using the same set operator as the one that combines the body and the initialization code.
18
+
19
+
There are two possible termination conditions. If the loop body includes the LIMIT clause, the loop terminates after the specified number of rows is processed. Alternatively, the loop terminates after processing all previously returned rows, with the loop body returning empty row sets.
20
+
21
+
<!--
22
+
More precisely, the processing frame is a single row view (in a sense, a pointer to the next exiting row of the processing queue) sitting at the tip of a dynamically generated processing queue, as discussed later.
0 commit comments