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