在光标中的情况

时间:2015-07-20 09:41:52

标签: sql oracle plsql

未经考验的水域,我试图找到一种方法来缓解问题。而不是在PL-SQL中的游标中嵌套选择。我试图在光标中创建一个案例。由于光标可以有不同的参数,我需要相应地对事物进行排序。

这可能吗?我的代码看起来像这样。它很容易阅读ao_in是Inparam。

PROCEDURE theProcedure (ao_in IN VARCHAR2)

CURSOR order_cur
  IS
 Case when ao_in = 'NIEC' 
  then          
      SELECT t1.nr, t1.status$nr
      FROM eh_order_t@NGEXT_DBLINK t1
      WHERE     t1.status$nr IN (3, 6)
      AND ao_in =
                     DECODE (ao_in, 'NIEC', ao_in, get_ehorder_ao (t1.nr))
              AND t1.nr = DECODE (order_in, NULL, t1.nr, order_in)
     ORDER BY t1.skapad_dat ASC;

  when ao_in = 'DSSP'  then
  SELECT t1.nr, t1.status$nr
      FROM eh_order_t@NGEXT_DBLINK t1
      WHERE     t1.status$nr IN (3, 6)
      AND ao_in =
                     DECODE (ao_in, 'DSSP', ao_in, get_ehorder_ao (t1.nr))
              AND t1.nr = DECODE (order_in, NULL, t1.nr, order_in)
     ORDER BY t1.skapad_dat ASC;
  when ao_in = 'ALLA'

  SELECT t1.nr, t1.status$nr
      FROM eh_order_t@NGEXT_DBLINK t1
      WHERE     t1.status$nr IN (3, 6)
      AND ao_in =
                     DECODE (ao_in, 'ALLA', ao_in, get_ehorder_ao (t1.nr))
              AND t1.nr = DECODE (order_in, NULL, t1.nr, order_in)
     ORDER BY t1.skapad_dat ASC;
  end

4 个答案:

答案 0 :(得分:1)

您可以使用OPEN-FOR语句完成所需的操作,如下所示:

PROCEDURE theProcedure (ao_in IN VARCHAR2)

    TYPE t_cur IS REF CURSOR;
    order_cur t_cur;

begin
    Case when ao_in = 'NIEC' 
      then  
        open order_cur for 
              SELECT t1.nr, t1.status$nr
              FROM eh_order_t@NGEXT_DBLINK t1
              WHERE     t1.status$nr IN (3, 6)
                AND ao_in = 'NIEC'
                AND t1.nr = DECODE (order_in, NULL, t1.nr, order_in)
             ORDER BY t1.skapad_dat ASC;

      when ao_in = 'DSSP'  then
        open order_cur for
              SELECT t1.nr, t1.status$nr
              FROM eh_order_t@NGEXT_DBLINK t1
              WHERE     t1.status$nr IN (3, 6)
                AND ao_in = 'DSSP'
                AND t1.nr = DECODE (order_in, NULL, t1.nr, order_in)
             ORDER BY t1.skapad_dat ASC;
      when ao_in = 'ALLA'
        open order_cur for
            SELECT t1.nr, t1.status$nr
            FROM eh_order_t@NGEXT_DBLINK t1
            WHERE     t1.status$nr IN (3, 6)
                AND ao_in ='ALLA'
                AND t1.nr = DECODE (order_in, NULL, t1.nr, order_in)
         ORDER BY t1.skapad_dat ASC;
    end;
end;

请注意,ao_in参数的解码评估不是必需的,因为已在case语句中对其进行了评估。 我假设order_in在原始代码中的某处声明,并且为了简化而未在此处发布,否则应该声明它。

答案 1 :(得分:1)

假设你的eh_order_t @ngext_dblink表中有一个名为“ao_in”的列,我认为你所追求的是这样的:

PROCEDURE theProcedure (p_ao_in IN VARCHAR2)
IS
  CURSOR order_cur
  IS
    SELECT t1.nr,
           t1.status$nr
    FROM   eh_order_t@NGEXT_DBLINK t1
    WHERE  t1.status$nr IN (3, 6)
    AND    (p_ao_in in ('NIEC', 'DSSP', 'ALLA')
            OR
            (p_ao_in not in ('NIEC', 'DSSP', 'ALLA') and ao_in = get_ehorder_ao (t1.nr)))
    AND    t1.nr = COALESCE(order_in, t1.nr)
    ORDER BY t1.skapad_dat ASC;
BEGIN
  FOR order_rec in order_cur
  LOOP
    -- do the things
  END LOOP;
END;
/

或者,你可以有两个游标,一个选择所有内容,一个过滤ao_in列,然后根据传入的参数调用相关的游标。我相信Oracle应该能够优化上面的基于传入的参数组合游标,但是如果你发现它不能或不想确定,将游标分成两个单独的游标将有助于优化器。

重要的是,您不应在PL / SQL中的游标中使用相同的参数或变量名称,因为优化程序可能会非常混淆,并且很可能会使您的and column_name = variable_of_same_name_as_column_name变为平均值and column_name = column_name,这可能不是你想要的!

ETA:如果在循环中完成的工作是DML,那么您可能可以完全取消游标并且只有一个DML语句。这将是最好的使用方案,因为逐行处理不是PL / SQL中最快的事情。基于集合的处理ftw! * {: - )

答案 2 :(得分:0)

让我们分析您的选择:

  SELECT t1.nr, t1.status$nr
  FROM eh_order_t@NGEXT_DBLINK t1
  WHERE     t1.status$nr IN (3, 6)
  AND ao_in =
                 DECODE (ao_in, 'DSSP', ao_in, get_ehorder_ao (t1.nr))
          AND t1.nr = DECODE (order_in, NULL, t1.nr, order_in)
 ORDER BY t1.skapad_dat ASC;

无论案例表达如何,条件ao_in = DECODE...始终为真 条件t1.nr = DECODE...可以重写为t1.nr = NVL(order_in, t1.nr),但order_in的定义在哪里? 结合:你的情况没有任何意义(并且不能以这种方式制作)。

如果要根据参数运行不同的select语句,请使用where条件并联合所有这些select语句。

答案 3 :(得分:0)

您可以使用参数光标link

例如:

CREATE TABLE tbl
(ID int, name varchar(50));

INSERT INTO tbl select 1, '0011' from dual;
INSERT INTO tbl select 1, '0012' from dual;
INSERT INTO tbl select 1, '0013' from dual;
INSERT INTO tbl select 1, '0014' from dual;
INSERT INTO tbl select 2, '0015' from dual;
INSERT INTO tbl select 2, '0016' from dual;
INSERT INTO tbl select 2, '0017' from dual;


set serveroutput on
declare 
    CURSOR para_cur(num NUMBER) IS select name from tbl where id = num;
begin
  dbms_output.put_line('for id = 1');
    FOR idx in para_cur(1) LOOP
        dbms_output.put_line(idx.name);
    end loop;

  dbms_output.put_line('for id = 2');
    FOR idx in para_cur(2) LOOP
        dbms_output.put_line(idx.name);
    end loop;
end;

out Put:

anonymous block completed
for id = 1
0011
0012
0013
0014
for id = 2
0015
0016
0017