【问题标题】:Getting data from the next row in Oracle cursor从 Oracle 游标中的下一行获取数据
【发布时间】:2010-06-15 06:59:53
【问题描述】:

我正在构建嵌套树,我需要使用 Oracle 获取游标中下一行的数据。而且我仍然需要当前行,因此向前循环不是解决方案。示例:

  OPEN emp_cv FOR sql_stmt;
  LOOP
  FETCH emp_cv INTO v_rcod,v_rname,v_level;
  EXIT WHEN emp_cv%NOTFOUND; 
  /*here lies the code for getting v_next_level*/
      if v_next_level > v_level then
          /*code here*/
          elsif v_next_level < v_level then
          /*code here*/
          else
          /*code here*/
          end if;
  END LOOP;
  CLOSE emp_cv;

【问题讨论】:

    标签: sql oracle database-cursor


    【解决方案1】:

    使用 LEAD 和 LAG 函数

    LEAD 能够计算下一行(将在当前行之后的行)的表达式并将值返回到当前行。 LEAD 的一般语法如下所示:

    LEAD (sql_expr, offset, default) OVER (analytic_clause)

    sql_expr 是从前导行计算的表达式。

    offset是前导行相对于当前行的索引。offset是一个正整数,默认为1。

    default 是指向分区范围外的行时返回的值。

    LAG 的语法类似,只是 LAG 的偏移量进入前几行。

    SELECT deptno, empno, sal,
    LEAD(sal, 1, 0) OVER (PARTITION BY dept ORDER BY sal DESC) NEXT_LOW_SAL,
    LAG(sal, 1, 0) OVER (PARTITION BY dept ORDER BY sal DESC) PREV_HIGH_SAL
    FROM emp
    WHERE deptno IN (10, 20)
    ORDER BY deptno, sal DESC;
    
     DEPTNO  EMPNO   SAL NEXT_LOWER_SAL PREV_HIGHER_SAL
    ------- ------ ----- -------------- ---------------
         10   7839  5000           2450               0
         10   7782  2450           1300            5000
         10   7934  1300              0            2450
         20   7788  3000           3000               0
         20   7902  3000           2975            3000
         20   7566  2975           1100            3000
         20   7876  1100            800            2975
         20   7369   800              0            1100
    
    8 rows selected.
    

    【讨论】:

    • 我正在使用“按名称排序兄弟姐妹”,Oracle 发誓。但是感谢您向我展示了如此出色的功能。
    【解决方案2】:

    我是这样做的。我正在倒退一步地建造一棵树。我必须检查第一次迭代。

    OPEN emp_cv FOR sql_stmt; 
     LOOP     
     if emp_cv%notfound then
        /*some code*/
        exit;
     end if;
     FETCH emp_cv INTO v_new_level;      
        if not b_first_time then    
          if v_new_level > v_level then
           /*some code*/
          elsif v_new_level < v_level then              
           /*some code*/
          else
           /*code*/
          end if;
        else    
          b_first_time:=false;
        end if;  
          v_level:=v_new_level;    
      END LOOP;
      CLOSE emp_cv;
    

    【讨论】:

      【解决方案3】:

      存储上一个级别并使用它会更好吗?类似于

        /* set to a value lesser than the lowest value possible for level
           am assuming 0 is the lowest value possible */
        v_previous_level := -1; 
      
        OPEN emp_cv FOR sql_stmt; 
        LOOP 
        FETCH emp_cv INTO v_rcod,v_rname,v_level; 
        EXIT WHEN emp_cv%NOTFOUND;  
            /* you'd probably have to update v_previous_level in one of 
               these conditions (depends on your logic) */
            if v_previous_level > v_level then 
                /*code here*/ 
                elsif v_previous_level < v_level then 
                /*code here*/ 
                else 
                /*code here*/ 
                end if; 
        END LOOP; 
        CLOSE emp_cv; 
      

      【讨论】:

      • 其实我已经试过了,它当然可以,但是我有特殊的 HTML 结构,这是 jQuery 插件所需要的,并且这种方法树无法正确构建。
      猜你喜欢
      • 2016-09-16
      • 1970-01-01
      • 1970-01-01
      • 2020-06-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-02-26
      相关资源
      最近更新 更多