有条件地定义一个 Cursor

发布于 2024-10-15 18:38:12 字数 622 浏览 3 评论 0原文

我在 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;

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 different tables based on the value of the parameter.

I wanted to do something like below but it throws an error in the CURSOR definition piece of code. Any ideas?

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;

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

逆蝶 2024-10-22 18:38:12

您将需要一个 REF CURSOR 并有条件地打开它,例如:

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

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
人│生佛魔见 2024-10-22 18:38:12

我可能会编写类似这样的代码(其中两个循环可能调用相同的函数)

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

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;
  ...
凹づ凸ル 2024-10-22 18:38:12

您甚至可以在隐式 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;

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;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文