I have the following table in an oracle:
Parent(arg1, arg2)
and I want the transitive closure of the relation parent. That is, I want the following table
Ancestor(arg1, arg2)
How is this possible in Oracle?
I am doing the following:
WITH Ancestor(arg1, arg2) AS (
SELECT p.arg1, p.arg2 from parent p
UNION
SELECT p.arg1 , a.arg2 from parent p, Ancestor a
WHERE p.arg2 = a.arg1
)
SELECT DISTINCT * FROM Ancestor;
I get the error
*Cause: column aliasing in WITH clause is not supported yet
*Action: specify aliasing in defintion subquery and retry
Error at Line: 1 Column: 20
How can I solve this without column aliasing?
Sometimes, to execute a SQL statement issued by a user, the Oracle Server must issue additional statements. Such statements are called recursive calls or recursive SQL statements.
PL/SQL Recursive FunctionsWhen a subprogram calls itself, it is referred to as a recursive call and the process is known as recursion. To illustrate the concept, let us calculate the factorial of a number. Factorial of a number n is defined as − n! = n*(n-1)! = n*(n-1)*(n-2)! ... = n*(n-1)*(n-2)*(n-3)...
Thus, a recursive CTE consists of a nonrecursive SELECT part followed by a recursive SELECT part. Each SELECT part can itself be a union of multiple SELECT statements. The types of the CTE result columns are inferred from the column types of the nonrecursive SELECT part only, and the columns are all nullable.
I mean, can I use recursion to have a function call itself? Answer: Yes, PL/SQL does support recursion via function calls. Recursion is the act of a function calling itself, and a recursive call requires PL/SQL to create local copies of its memory structures for each call.
WITH Ancestor(arg1, arg2) AS
(
SELECT p.arg1, p.arg2
FROM parent p
WHERE arg2 NOT IN
(
SELECT arg1
FROM parent
)
UNION ALL
SELECT p.arg1, a.arg2
FROM Ancestor a
JOIN parent p
ON p.arg2 = a.arg1
)
SELECT *
FROM Ancestor
Oracle
only supports recursive CTE
since 11g
Release 2.
In earlier versions, use CONNECT BY
clause:
SELECT arg1, CONNECT_BY_ROOT arg2
FROM parent
START WITH
arg2 NOT IN
(
SELECT arg1
FROM parent
)
CONNECT BY
arg2 = PRIOR arg1
Oracle allows recursive queries. See: http://www.adp-gmbh.ch/ora/sql/connect_by.html
Of course, these usually assume the hierarchical data is all in one table. Splitting it into separate tables makes things complicated.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With