来自Cursor的Oracle Last Records

时间:2018-05-15 11:38:35

标签: sql oracle plsql

我有以下代码。对于光标的最后一行,我不需要打印' - >'符号。如果运行查询,则可以看到第四条记录显示两次

declare
cursor ch is
  select 1 as n from dual union
  select 2 from dual union 
  select 3 from dual union
  select 4 from dual;
v_ch ch%rowtype;
begin

  open ch;
  loop
    fetch ch into v_ch;
    exit when ch%notfound;
    dbms_output.put_line(LPAD(' ',5)||v_ch.n || '->');

  end loop;
  dbms_output.put_line(LPAD(' ',5)||v_ch.n);
  close ch;
end;

结果

 1->
 2->
 3->
 4->
 4

2 个答案:

答案 0 :(得分:4)

PL / SQL解决方案

这将有效,只需稍微改变何时打印箭头/换行符:

set serveroutput on
declare
cursor ch is
  select 1 as n from dual union
  select 2 from dual union 
  select 3 from dual union
  select 4 from dual;
v_ch ch%rowtype;
first boolean := true;
begin

  open ch;
  loop
    fetch ch into v_ch;
    exit when ch%notfound;

    -- Append the arrow after all rows except the first and implicitly (because of the
    -- above exit) except the last, too
    if not first then
      dbms_output.put_line('->');
    end if;
    first := false;

    -- Use put here, instead of put_line, such that the arrow will be appended on the
    -- same line as the value on the next loop iteration
    dbms_output.put(LPAD(' ',5)||v_ch.n);
  end loop;

  -- Finally, print a newline character
  dbms_output.put_line('');
  close ch;
end;
/

SQL解决方案

当然,您也可以在SQL中生成箭头:

set serveroutput on
declare
cursor ch is
  select n, case 
    when row_number() over (order by n) = 
         count(*) over () then '' else '->' end arrow
  from (
      select 1 as n from dual union
      select 2 from dual union 
      select 3 from dual union
      select 4 from dual
  ) t;
v_ch ch%rowtype;
begin
  open ch;
  loop
    fetch ch into v_ch;
    exit when ch%notfound;
    dbms_output.put_line(LPAD(' ',5)||v_ch.n||v_ch.arrow);
  end loop;
  dbms_output.put_line('');
  close ch;
end;
/

甚至:

select listagg(n, '->' || chr(10)) within group (order by n)
from (
  select 1 as n from dual union
  select 2 from dual union 
  select 3 from dual union
  select 4 from dual
);

这仅适用于您的字符串未达到VARCHAR2长度限制

的情况

答案 1 :(得分:3)

您可以修改光标以识别每行的位置;没有任何有点笨重的订购信息:

declare
cursor ch is
  select n, count(*) over () - rownum as c from (
    select 1 as n from dual union
    select 2 from dual union 
    select 3 from dual union
    select 4 from dual
  );
v_ch ch%rowtype;
begin

  open ch;
  loop
    fetch ch into v_ch;
    exit when ch%notfound;
    dbms_output.put_line(LPAD(' ',5)||v_ch.n || case when v_ch.c > 0 then '->' end);
  end loop;
  close ch;
end;
/

     1->
     2->
     3->
     4


PL/SQL procedure successfully completed.

在此示例中,c列对于返回的最后一行为零;所以输出使用case表达式只显示大于零的箭头 - 即除最后一行之外的所有箭头。

使用真正的查询,您可以使用row_number() over (order by <something> desc将列添加到当前结果集,这将使最后一行成为#1,您可以将显示逻辑基于此。您可能也不需要子查询。我们无法看到您的真实查询,因此只能猜测如何最好地应用它。