【问题标题】:PL/SQL cursor with IF condition带有 IF 条件的 PL/SQL 游标
【发布时间】:2014-11-26 11:06:21
【问题描述】:

我在代码中有下面的光标。

   CURSOR cur1
   IS
      SELECT a, b, c, d,
        FROM EMP;
BEGIN
    --Stored procedure logic
END

此游标正在从 EMP 表中获取信息。

但我需要更改如下

  • 有一个包含键值对的表 (Table1)。
  • 如果 Table1 的值为 TRUE,则应使用 STUDENT 表创建游标
  • 如果 table1 的值为 FALSE,则应使用 EMP 表创建游标。

我可以检查表1中的值,如下所示

select t.value into variable1 from Table1 t where s.key='xxxxx';

我想写一些类似的东西

IF variable1 := 'true'
 curosr created with STUDENT
 ELSE
  curosr created with EMP
END IF

BEGIN
    --Stored procedure logic
END

怎么做?

【问题讨论】:

  • 您使用的是哪个 RDBMS?
  • 我正在使用 Oracle(PL/SQL 工具开发人员)。我是这个领域的初学者。
  • 尽可能多地使用布尔值。 'true' 是一个 VARCHAR2

标签: sql oracle stored-procedures plsql


【解决方案1】:

您可以将 OPEN 移到 IF 语句之外:

    DECLARE type cur1 REF CURSOR;
    c1 cur1;

    vSQL VARCHAR2(1000);

    BEGIN
        IF (variable1 = 'true') THEN 
            vSQL := 'SELECT * FROM STUDENT'; 
        ELSE 
            vSQL := 'SELECT * FORM EMP';
        END IF; 
        OPEN c1 FOR vSQL;
        --procedure logic
        CLOSE c1;
    END;

【讨论】:

    【解决方案2】:

    以另一种方式,您可以为这两个场景保留两个 CURSORS 并在条件下打开它们。声明两个 CURSORS 不会影响性能;在打开一个 CURSOR 并从中获取时要小心。

    PROCEDURE Get_Details_On_Condition ( name_ OUT VARCHAR2, isEmp IN BOOLEAN )
    IS
      CURSOR get_emp IS
         SELECT name
         FROM EMP;
      CURSOR get_std IS
         SELECT name
         FROM STUDENT;
    BEGIN
       IF isEmp THEN
          OPEN get_emp ;
          FETCH get_emp INTO name_ ;
          CLOSE get_emp ;
       ELSE
          OPEN get_std ;
          FETCH get_std INTO name_ ;
          CLOSE get_std ;
       END IF;
    RETURN name_;
    END Get_Details_On_Condition;
    

    【讨论】:

      【解决方案3】:

      我宁愿在不使用动态 SQL 的情况下解决这个问题。如果两个表处理结果的代码相同,则可以合理地假设列也相同(或等效)。我倾向于使用UNION 和子查询来解决这个问题:

      DECLARE
         CURSOR cur1 IS
            SELECT a, b, c, d
            FROM   emp
            WHERE  NOT EXISTS
                      (SELECT *
                       FROM   table1
                       WHERE  s.key = 'xxxxx' AND t.VALUE = 'true')
            UNION ALL
            SELECT a, b, c, d
            FROM   student
            WHERE  EXISTS
                      (SELECT *
                       FROM   table1
                       WHERE  s.key = 'xxxxx' AND t.VALUE = 'true');
      BEGIN
        --Stored procedure logic
      END;
      

      【讨论】:

        【解决方案4】:

        使用if .. else 构造是不正确的(都不支持)。您可以使用REF cursor 来实现如下所示。

         DECLARE type cur1 REF CURSOR;
         c1 cur1;
        
          BEGIN 
           IF (variable1 := 'true') THEN 
             OPEN c1 FOR 'SELECT * FROM STUDENT'; 
           ELSE 
             OPEN c1 FOR 'SELECT * FORM EMP';
         END IF ; 
          END; 
        

        想法来自Oracle Community Forum Post

        注意:我没有包含整个代码块(我的意思是游标处理、关闭等),因为这里主要关注的是“他将如何声明/定义条件游标”。因此,在我的代码 sn-p 中指出了这一点。因为,处理游标和关闭等其余部分可以直接在Oracle规范中找到。

        完整的代码块可以参考Harsh给出的答案

        【讨论】:

        • 我收到以下异常 PROCEDURE SCHEMA1.IMPORT 的编译错误错误:PLS-00103:在预期以下情况之一时遇到符号“DECLARE”:开始函数包编译指示过程子类型类型使用 form current cursor Line: 44 Text: DECLARE
        • @Shyam534 在过程或函数中使用此代码 sn-p 时,不需要DECLARE
        • Rahul,如果你修正你的答案会很好,因为就目前而言,即使你确实回答了这个问题,它也非常不完整。正如@Harsh 部分建议的那样,我正在考虑TYPE 声明、CLOSE 声明以及为什么不考虑对最近打开的游标进行一次迭代。
        • @Sebas,感谢您的编辑。是的,我没有包含整个代码块(我的意思是游标处理、关闭等)导致 OP 的主要关注点是“他将如何声明/定义条件游标”。因此,在我的代码 sn-p 中指出了这一点。因为,处理游标和关闭等其余部分可以直接在Oracle规范中找到。
        • 是的,你是对的。你介意删除END 语句吗?或者在您的代码中添加一些 cmets 提到该语句不完整?我正在考虑使用我们的代码的初学者。
        【解决方案5】:

        Rahul 提供的链接指出了解决问题的正确方法。从 Rahul 发布的 Oracle 社区论坛帖子中,我获取了代码可以成功运行的代码 sn-p。

        Rahul:请不要将此视为多余的答案,因为我无法评论您的答案以帮助 shyam 获取您发布的链接中的代码 sn-p。

            Declare
        
        TYPE cv_typ IS REF CURSOR;
             cv cv_typ;
        
        Begin
        If(condition1 is TRUE) then
             open cv FOR
             'Select * from table_name1';
             EXIT WHEN cv%NOTFOUND;
        ELSE
             open cv FOR
             'Select * from table_name2';
             EXIT WHEN cv%NOTFOUND;
        
        End If;
        
             CLOSE cv;
        END; 
        

        感谢和问候, 苛刻

        【讨论】:

        • 不需要您的回答。它并没有给 Rahul 的答案带来更多。
        • sebas:我在回答中确实说过,它取自 rahul 提供的链接。为了帮助 shyam 使用正确的代码 sn-p 来解决他的问题,我向他发布了正确的代码 sn-p。
        • 我看不出与拉胡尔的回答有什么不同。您发布的内容完全相同,只是您没有使用 OP 的查询。编辑:确实你添加了 TYPE 声明......我不确定它是否证明了另一个答案。我会在另一个答案中为您添加评论。
        • 虽然,@Sebas 指出的是正确的(答案的核心是相同的),但是您已经包含了其余部分,例如 TYPE 声明,完成后关闭。在这种情况下,它不能被认为是完全没用的。 +1 用于完成代码块。
        • @Allan 谢谢,这是有效的解决方案其他人感谢您的帮助:-)
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-01-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多