2011-02-01 32 views
6

我在Oracle中有一个过程需要varchar2参数。根据该参数的值,我需要定义一个游标。根据参数的值,光标将在不同的表格上运行。有条件地定义一个光标

我想做一些像下面,但它引发的CURSOR定义的代码错误。有任何想法吗?

PROCEDURE GET_RECORDS(v_action IN VARCHAR2) 
IS 
CURSOR get_records 
IS 
     IF(v_action = 'DO THIS') THEN 
      SELECT * from <THIS>; 
     ELSE 
      SELECT * from <THAT>; 
     END IF; 
BEGIN 
     OPEN get_records; 

     FETCH get_records 
     INTO v_thing; 

     v_loop := 0; 
     WHILE get_records%FOUND 
     LOOP 

      FETCH get_records 
      INTO v_thing; 

     END LOOP; 
     CLOSE get_records; 
END; 

回答

8

,您将需要一个REF CURSOR和conditionaly打开它,例如:

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

@Vincent ...这是炸弹!很好的作品....谢谢 – MikeTWebb 2011-02-01 15:56:18

2

我可能会代码是这样的(其中两个回路可以调用相同的功能)

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; 

你也可以使用动态SQL打开游标但往往变得更加复杂,特别是如果只有两种选择。

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; 
    ... 
1

你甚至可以使用的条件隐含在for循环中。没有游标声明或SYS_REFCURSOR(我不喜欢他们抱歉) - 我的意思是,你可以用你的变量,这里v_action,隐式游标声明中:

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;