-1

Inside a stored procedure, I am trying to set value of a declared varchar(100) variable 'my_path' based on a virtual dataset created via a WITH and recursive CTE statement.

First I tried "SELECT INTO", but got "missing keyword" error.

I can alternatively think of updating a table row with value of 'path' from WITH statement, but then I get "missing select keyword" error and I have understood that I cannot UPDATE with CTE in Oracle SQL server. But is there any way to access the output of recursive CTE then? I need it later in my stored procedure.

declare mypath varchar(100);
begin
with CTE (toN,path,done)
as
(
-- anchor
select
cap.toN,
concat(concat(CAST(cap.fromN as varchar(10)) , ',') , CAST(cap.toN as varchar(10))),
case when cap.toN = 10000 then 1 else 0 end
from cap 
where
(fromN = 1) and (cap.cap_up > 0)

union all
-- recursive
select
cap.toN, 
concat(concat(path,','), CAST(cap.toN as varchar(10)) ),
case when cap.toN=10000 then 1 else 0 end
from cap join cte on 
cap.fromN = cte.toN
where
(cap.cap_up > 0) and (cte.done = 0)
)
select path into mypath from cte where done=1
);
end;
Matin
  • 117
  • 5
  • 15

2 Answers2

1

I think your code should work. It does have a lingering closing paren, which is suspicious.

Perhaps some simplification will help:

with CTE(toN, path, done) as (
-- anchor
      select cap.toN, cap.fromN || ',' || cap.toN 
             (case when cap.toN = 10000 then 1 else 0 end)
     from cap 
     where fromN = 1 and cap.cap_up > 0
     union all
     -- recursive
     select cap.toN, path || ',' || cap.toN,
            (case when cap.to = 10000 then 1 else 0 end)
     from cap join
          cte 
          on cap.fromN = cte.toN
     where cap.cap_up > 0 and cte.done = 0
    )
select path into my_path
from cte
where done = 1;
Gordon Linoff
  • 1,242,037
  • 58
  • 646
  • 786
1

Now that you have fixed the variable names... you still need a third column for the CTE to contain the toN that is in the join condition of your recursive part of the query. There is also a trailing ) bracket a the end of the query and you can use || to concatenate strings (which you do not need to cast to varchars).

WITH CTE (path,done, toN) as (
  -- anchor
  SELECT fromN || ',' || toN,
         CASE WHEN toN = 10000 THEN 1 ELSE 0 END,
         toN
  FROM   cap 
  WHERE  "FROM" = 1
  AND    cap_up > 0
UNION ALL
  -- recursive
  SELECT cte.path || ',' || cap.toN,
         CASE WHEN cap.toN =10000 THEN 1 ELSE 0 END,
         cap.toN
  FROM   cap
         join cte
         on   ( cap.fromN = cte.toN )
  WHERE  cap.cap_up > 0
  AND    cte.done = 0)
)
select path into my_path from cte where done=1;

A simpler solution would be to use a hierarchical query.

SELECT SUBSTR( SYS_CONNECT_BY_PATH( fromN, ',' ), 2 ) || ',' || toN
INTO   mypath
FROM   cap
WHERE  toN = 10000
START WITH fromN = 1
CONNECT BY PRIOR toN = fromN;
MT0
  • 143,790
  • 11
  • 59
  • 117