oracle中的多行迭代

时间:2018-01-08 15:28:42

标签: sql oracle

我有oracle sql的问题。

DECLARE r_cur select cma.desc, cma.model, cma.serial, smp.id
from model cma
join dictionary smp on smp.dictionary_id = cma.d_id;

以上将返回2行。我也有变数,比方说 v_var ,可以为null或具有某些值。

然后我想根据v_var的值迭代r_cur。 所以我想要这样的东西:

fetch r_cur into r_cur_single
if v_var is null then
select r_cur.desc, r_cur.model etc. into v_description, v_mode from r_cur where r_cur.serial is null
else 
select r_cur.desc, r_cur.model etc. into v_description, v_mode from r_cur where r_cur.serial like v_var

Oracle Developer返回一个错误,它无法从非表或视图中进行选择,但不应该以相同的方式使用游标。如果没有办法迭代这样的光标,甚至可能在select中使用 CASE 。我试过但问题是v_var可以为null。

2 个答案:

答案 0 :(得分:1)

游标实际上是指向结果集的指针。你不能像表那样查询光标。

您可以在游标查询中引用v_var;你只需处理它为null:

DECLARE
  v_var model.serial%type;

  cursor r_cur is
    select cma.desc, cma.model, cma.serial, smp.id
    from model cma
    join dictionary smp on smp.dictionary_id = cma.d_id
    where (v_var is null and cma.serial is null)
    or (v_var is not null and cma.serial = v_var);
BEGIN
  -- populate v_var
  FOR r_row IN r_cur LOOP
    -- do whatever you need to with the row(s)
  END LOOP;
END;
/

is not null有点多余,但逻辑更清晰。将like与单个标量值一起使用也毫无意义,因此我已切换到=

您还可以参数化光标以使关系和流程更加明显:

DECLARE
  v_var model.serial%type;

  cursor r_cur (c_var model.serial%type) is
    select cma.desc, cma.model, cma.serial, smp.id
    from model cma
    join dictionary smp on smp.dictionary_id = cma.d_id
    where (c_var is null and cma.serial is null)
    or (c_var is not null and cma.serial = c_var);
BEGIN
  -- populate v_var
  FOR r_row IN r_cur (v_var) LOOP
    -- do whatever you need to with the row(s)
  END LOOP;
END;
/

或者使用隐式游标循环:

DECLARE
  v_var model.serial%type;
BEGIN
  -- populate v_var
  FOR r_rec IN (
    select cma.desc, cma.model, cma.serial, smp.id
    from model cma
    join dictionary smp on smp.dictionary_id = cma.d_id
    where (v_var is null and cma.serial is null)
    or (v_var is not null and cma.serial = v_var)
  ) LOOP
    -- do whatever you need to with the row(s)
  END LOOP;
END;
/

仍然可以保留当前游标查询并循环遍历所有结果,使用循环内部的类似逻辑来确定何时找到要使用的行,然后使用PL / SQL分配而不是新查询:

fetch r_cur into r_cur_single;
if (v_var is null and r_cur_single.serial is null)
  or (v_var is not null and r_cur_single.serial = v_var)
then
  v_description := r_cur_single.desc;
  v_mode := r_cur_single.model;
end if;

但是将过滤器放入查询可能会更有效率。

答案 1 :(得分:0)

有很多方法可以解决这个问题...一个简单的方法是声明2个游标:一个使用like表达式,另一个使用IS NULL表达式...然后,你打开右边IF ELSE v_var中的游标不是空逻辑...