Conditionally define a Cursor

后端 未结 3 1942
鱼传尺愫
鱼传尺愫 2020-12-19 07:34

I have a Procedure in Oracle that takes a varchar2 paramater. Based on the value of that parameter, I need to define a cursor. The cursor will operate on diff

相关标签:
3条回答
  • 2020-12-19 07:47

    you will need a REF CURSOR and open it conditionaly, for example:

    SQL> CREATE OR REPLACE PROCEDURE GET_RECORDS(v_action IN VARCHAR2) IS
      2     v_thing     VARCHAR2(10);
      3     get_records SYS_REFCURSOR;
      4  BEGIN
      5     IF (v_action = 'DO THIS') THEN
      6        OPEN get_records FOR
      7           SELECT 1 FROM dual;
      8     ELSE
      9        OPEN get_records FOR
     10           SELECT 2 FROM dual;
     11     END IF;
     12  
     13     LOOP
     14        FETCH get_records INTO v_thing;
     15        EXIT WHEN get_records%NOTFOUND;
     16        /* do things */
     17        dbms_output.put_line(v_thing);
     18     END LOOP;
     19     CLOSE get_records;
     20  END;
     21  /
    
    Procedure created
    
    SQL> exec get_records ('DO THIS');
    1
    
    PL/SQL procedure successfully completed
    
    SQL> exec get_records ('DO THAT');
    2
    
    PL/SQL procedure successfully completed
    
    0 讨论(0)
  • 2020-12-19 07:54

    You can even use the condition inside the implicit for loop. Without cursor declaration or SYS_REFCURSOR (I dislike them sorry) - I mean you can use your variables, here v_action, inside implicit cursor declaration:

    BEGIN
        FOR this_cur IN (
           SELECT * FROM <THIS> 
            WHERE v_action = 'DO THIS'
        ) LOOP
          <<do something>>
        END LOOP;
        FOR that_cur IN (
           SELECT * FROM <THIS> 
            WHERE v_action <> 'DO THIS'
        ) LOOP
          <<do something else>>
        END LOOP;
      END IF;
    END;
    
    0 讨论(0)
  • 2020-12-19 08:01

    I would probably code something like this (where the two loops may call the same functions)

    BEGIN
      IF( v_action = 'DO THIS' )
      THEN
        FOR this_cur IN (SELECT * FROM <THIS>)
        LOOP
          <<do something>>
        END LOOP;
      ELSE
        FOR that_cur IN (SELECT * FROM <THAT>)
        LOOP
          <<do something else>>
        END LOOP;
      END IF;
    END;
    

    You could also use dynamic SQL to open the cursor but that tends to get more complicated, particularly if there are only two options.

    IS
      get_records SYS_REFCURSOR;
      l_sql_stmt  VARCHAR2(100);
    BEGIN
      IF( v_action = 'DO THIS' )
      THEN
        l_sql_stmt := 'SELECT * from <THIS>';
      ELSE
        l_sql_stmt := 'SELECT * from <THAT>';
      END IF;
    
      OPEN get_records FOR l_sql_stmt;
      ...
    
    0 讨论(0)
提交回复
热议问题