Reputation: 579
I have the following piece of code. For the last line of the cursor I don't need to print the '->' symbol. If you run the query you can see that the fourth record is displayed twice
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;
result
1->
2->
3->
4->
4
Upvotes: 3
Views: 9309
Reputation: 220762
This will work, just a bit of shifting when to print arrows / newlines:
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;
/
Of course, you can generate the arrow also in 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;
/
Or even:
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
);
This only works if your string won't reach the VARCHAR2
length limit
Upvotes: 4
Reputation: 191245
You could modify the cursor to identify the position of each row; without any ordering information that's a bit clunky:
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.
In this example the c
column is zero for the final row returned; so the output uses a case expression to only show the arrow when that is greater than zero - i.e. all except that last row.
With a real query you might be able to just add a column to the current result set using row_number() over (order by <something> desc
, which would make the last row #1, and you could base the display logic on that instead. You probably wouldn't need a subquery then either. We can't see your real query though so can only guess how it can best be applied.
Upvotes: 3