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
Recursive CTEs enable the implementation of the following task. Suppose we have a set of file system directory paths and a set of COPY operations defined as the original and new paths. We need an SQL query to perform this transformation. The RCTE feature is the only way to implement this transformation in SQL/SQLite because of potential successive modifications. The snippet below shows only the core code (the LOOP_COPY block) without further processing. Note that straightforward use of the _replace_ routine would be incorrect because of possible matches in the middle of the path.
-- Place input rows in the processing queue for the next loop
34
+
SELECTops.opid, path_new
35
+
FROM LOOP_COPY AS BUFFER, ops
36
+
WHEREops.opid=BUFFER.opid+1
37
+
UNION ALL
38
+
-- Append the processing queue with new paths generated by the current operation
39
+
SELECTops.opid,
40
+
rootpath_new || substr(path_new, length(rootpath_old)) AS path_new
41
+
FROM LOOP_COPY AS BUFFER, ops
42
+
WHEREops.opid=BUFFER.opid+1
43
+
ANDBUFFER.path_newlike rootpath_old ||'%'
44
+
)
45
+
SELECT*FROM LOOP_COPY;
46
+
~~~
47
+
48
+
Note that this task is still not particularly well suited for SQL. The initial SELECT places all paths in the processing queue, making them available in the first loop cycle. Because the COPY operation does not delete any folders, the entire input must be placed in the processing queue for the next loop cycle, meaning that the initial set and all previously created paths are duplicated during each loop cycle.
49
+
50
+
Even though the RCTE loop body processes one row at a time, when the processing queue acts as FIFO (the default behavior), it might be helpful to treat the RCTE loop as if it processed the entire row set produced by the preceding cycle. When the processing queue acts as FIFO, this treatment is appropriate, as illustrated by the two tables above (compare the output of *Loop Cycle #1* shown in the first table with the column *Cycle #3* from the second table). The query below shows an equivalent implementation of the RCTE block (only valid for the given input), which unravels the above *LOOP_COPY* RCTE.
Copy file name to clipboardExpand all lines: Patterns Recursive CTEs.md
+1-129Lines changed: 1 addition & 129 deletions
Original file line number
Diff line number
Diff line change
@@ -6,7 +6,7 @@ parent: Design Patterns
6
6
permalink: /patterns/rec-cte
7
7
---
8
8
9
-
### Recursive CTE structure vs. While/Repeat Loop
9
+
### Recursive CTE structure vs. While/Repeat loop
10
10
11
11
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 using the standard SELECT grammar/syntax (except for the self-reference) and a special convention. The result is quite contrived, so comprehending and mastering RCTEs may not be straightforward.
12
12
@@ -44,134 +44,6 @@ The table below shows a proper representation of the processing queue. This tabl
44
44
|| row 1.2 | row 1.3 | row 2.1 |
45
45
|| row 1.3 | row 2.1 | row 3.1 |
46
46
47
-
Recursive CTEs enable the implementation of the following task. Suppose we have a set of file system directory paths and a set of COPY operations defined as the original and new paths. We need an SQL query to perform this transformation. The RCTE feature is the only way to implement this transformation in SQL/SQLite because of potential successive modifications. The snippet below shows only the core code (the LOOP_COPY block) without further processing. Note that straightforward use of the _replace_ routine would be incorrect because of possible matches in the middle of the path.
-- Place input rows in the processing queue for the next loop
72
-
SELECTops.opid, path_new
73
-
FROM LOOP_COPY AS BUFFER, ops
74
-
WHEREops.opid=BUFFER.opid+1
75
-
UNION ALL
76
-
-- Append the processing queue with new paths generated by the current operation
77
-
SELECTops.opid,
78
-
rootpath_new || substr(path_new, length(rootpath_old)) AS path_new
79
-
FROM LOOP_COPY AS BUFFER, ops
80
-
WHEREops.opid=BUFFER.opid+1
81
-
ANDBUFFER.path_newlike rootpath_old ||'%'
82
-
)
83
-
SELECT*FROM LOOP_COPY;
84
-
~~~
85
-
86
-
Note that this task is still not particularly well suited for SQL. The initial SELECT places all paths in the processing queue, making them available in the first loop cycle. Because the COPY operation does not delete any folders, the entire input must be placed in the processing queue for the next loop cycle, meaning that the initial set and all previously created paths are duplicated during each loop cycle.
87
-
88
-
Even though the RCTE loop body processes one row at a time, when the processing queue acts as FIFO (the default behavior), it might be helpful to treat the RCTE loop as if it processed the entire row set produced by the preceding cycle. When the processing queue acts as FIFO, this treatment is appropriate, as illustrated by the two tables above (compare the output of *Loop Cycle #1* shown in the first table with the column *Cycle #3* from the second table). The query below shows an equivalent implementation of the RCTE block (only valid for the given input), which unravels the above *LOOP_COPY* RCTE.
0 commit comments