Search code examples
plsqlcursor

Using cursors in loop in PL/SQL


I have table that contains 3 column.First column name is id , second column's name is parent_id and third one is expression.What i want to do is to search expression column for id.For example I send id value then if parent_id column has a value I want to send parent_id value and want to check expression column has 'E' or not.If It has null value and result has parent_id then I want to send parent_id value and again I want to check expression column has 'E' or not.If expression column has a value like that 'E', I updated variable resultValue as 1 and end loop.

my table A : It should return resultValue =1

id  |parent_id|expression
123 |null     | null
45  |123      | 'E'
22  |45       | null

my table B : It should return resultValue = 0

id  |parent_id|expression
30  |null     | null
20  |30       | null
10  |20       | null

my table C : It should return resultValue = 0

id  |parent_id|expression
30  |null     | null
20  |30       | null
10  |null     | null

If first sending id(10) does not contain parent_id(table C) resultValue variable should be 0. If I find 'E' expression any parent row resultValue variable should return 1.

I created a code block with cursor.For the first time I used cursor.I am not sure using cursor with this kind of problem is a good idea or not.My code is running but to open cursor then to close cursor then again opening cursor it is good idea?

DECLARE
  resultValue NUMBER := 0;
  CURSOR c(v_id NUMBER )
  IS
    SELECT id_value, id_parent, expression FROM students WHERE id_value = v_id;
PROCEDURE print_overpaid
IS
  id_value   NUMBER;
  id_parent  NUMBER;
  expression VARCHAR2(20);
BEGIN
  LOOP
    FETCH c INTO id_value, id_parent, expression;
    EXIT
  WHEN c%NOTFOUND;
    IF id_parent IS NULL AND expression IS NULL THEN
      EXIT;
    END IF;
    IF id_parent IS NOT NULL THEN
      CLOSE c;
      OPEN c(id_parent);
    ELSIF id_parent <> NULL AND expression = 'X' OR id_parent IS NULL AND expression = 'X' THEN
      resultValue   := 1;
      EXIT;
    END IF;
   END LOOP;
END print_overpaid;
BEGIN
  OPEN c(22);
  print_overpaid;
  DBMS_OUTPUT.PUT_LINE('  My resultValue is : ' || resultValue);
  CLOSE c;
END;

Solution

  • If I understood your description correctly, you are looking to see it the specified id of any row in the parentage contains 'E' in the column expression. You are correct that closing and reopening a cursor is not really a good idea. Although I do like your use of a nested procedure. However, it's not really necessary as this can be solved with a single query. The approach will be a recursive CTE that checks the target row for 'E' until a row contains it or the row does not have a parent.

    with search_for_e(id, parent_id, e_cnt) as 
         ( select id, parent_id, case when expression = 'E' then 1 else 0 end 
             from exp_tbl
           where id = &id
           union all 
           select t.id,t.parent_id, case when t.expression = 'E' then 1 else 0 end
           from search_for_e s
           join exp_tbl t on (t.id = s.parent_id) 
           where t.parent_id is not null 
             and s.e_cnt = 0
       ) 
    select max(e_cnt) 
      from search_for_e;
    

    See fiddle here, it also contains an anonymous block implementation with nested function and one with cursor.