From: esmith2112 on
Within the confines of a stored procedure how do I declare a cursor to
return a result set to the client application, and also update a non-
returned attribute of each row? For example using pseudo-SQL, my non-
functioning attempt:

=================
declare curs1 cursor with return for
select t_id, t_name
from mytable
where sent_timestamp is null;


--perform update on each row
open curs1;
while (<not at end of cursor>)
fetch curs1 into my_t_id, my_t_name;

update mytable
set sent_timestamp = current timestamp
where t_id = my_id;
end while;

--return results to client
open curs1;


================

This reminds me of the Halloween problem a little. But evening
googling didn't provide an ready answer.

Using 9.5 on AIX 5.3.

Thanks,
Evan

P.S. Anyone know how to get Google Groups to search this archive past
the most recent 30 days?
From: jefftyzzer on
On Sep 28, 9:41 am, esmith2112 <esmith2...(a)gmail.com> wrote:
> Within the confines of a stored procedure how do I declare a cursor to
> return a result set to the client application, and also update a non-
> returned attribute of each row? For example using pseudo-SQL, my non-
> functioning attempt:
>
> =================
> declare curs1 cursor with return for
>    select t_id, t_name
>    from mytable
>    where sent_timestamp is null;
>
> --perform update on each row
> open curs1;
> while (<not at end of cursor>)
>     fetch curs1 into my_t_id, my_t_name;
>
>     update mytable
>     set sent_timestamp = current timestamp
>     where t_id = my_id;
> end while;
>
> --return results to client
> open curs1;
>
> ================
>
> This reminds me of the Halloween problem a little. But evening
> googling didn't provide an ready answer.
>
> Using 9.5 on AIX 5.3.
>
> Thanks,
> Evan
>
> P.S. Anyone know how to get Google Groups to search this archive past
> the most recent 30 days?

Why do you need a cursor at all? Why not just do

update mytable
set sent_timestamp = current timestamp
where sent_timestamp is null;

and then

open curs1;

If you really do need to loop, I think you're better off using a
cursor FOR loop (much faster than open...while...fetch), like so:

FOR l_mytab as c_mytab cursor for
select t_id, t_name
from mytable
where sent_timestamp is null

DO
update mytable
set sent_timestamp = current timestamp
where t_id = l_mytab.id;--

end for;--

As to returning the cursor, the easiest thing to do would be to simply
declare it as before and open it after the update, i.e., put the "open
curs1;" after the "end for;"

For something even crazier (and likely faster), you could do this:

declare curs1 cursor with return for
select t_id, t_name
from
final table
(update mytable
set sent_timestamp = current timestamp
where sent_timestamp is null
);--

open curs1;--

--Jeff
From: esmith2112 on
On Sep 28, 2:00 pm, jefftyzzer <jefftyz...(a)sbcglobal.net> wrote:
> On Sep 28, 9:41 am, esmith2112 <esmith2...(a)gmail.com> wrote:
>
>
>
>
> Why do you need a cursor at all? Why not just do
>
> update mytable
> set sent_timestamp = current timestamp
> where sent_timestamp is null;
>
> and then
>
> open curs1;
>
> If you really do need to loop, I think you're better off using a
> cursor FOR loop (much faster than open...while...fetch), like so:
>
> FOR l_mytab as c_mytab cursor for
>    select t_id, t_name
>    from mytable
>    where sent_timestamp is null
>
> DO
>      update mytable
>      set sent_timestamp = current timestamp
>      where t_id = l_mytab.id;--
>
> end for;--
>
> As to returning the cursor, the easiest thing to do would be to simply
> declare it as before and open it after the update, i.e., put the "open
> curs1;" after the "end for;"
>
> For something even crazier (and likely faster), you could do this:
>
> declare curs1 cursor with return for
> select t_id, t_name
> from
> final table
> (update mytable
> set sent_timestamp = current timestamp
> where sent_timestamp is null
> );--
>
> open curs1;--
>
> --Jeff

Thanks, Jeff. I'll give your suggestions a shot. I haven't done
application development in a long while, so my skills are definitely
rusty. I knew I was probably missing a fundamental concept here.
From: Mark A on
> "esmith2112" <esmith2112(a)gmail.com> wrote in message
> news:aae8aab2-00b0-405e-930b-84a33241f175(a)g23g2000yqh.googlegroups.com...
> Thanks, Jeff. I'll give your suggestions a shot. I haven't done
> application development in a long while, so my skills are definitely
> rusty. I knew I was probably missing a fundamental concept here.

Don't be too hard on yourself. There are some potential problems doing the
update in one statement, such as filling up the transaction log and/or
holding a lot of locks on the table--thereby decreasing concurrency. With a
cursor, you can commit every N updates, and if the cursor is defined WITH
HOLD, then it will not close when a commit is issued.

I don't now if these issues apply in your circumstance, but there are
legitimate reasons for using a cursor, even if the elapsed time is a bit
slower.


From: jefftyzzer on
On Sep 28, 11:30 am, esmith2112 <esmith2...(a)gmail.com> wrote:
> On Sep 28, 2:00 pm, jefftyzzer <jefftyz...(a)sbcglobal.net> wrote:
>
>
>
> > On Sep 28, 9:41 am, esmith2112 <esmith2...(a)gmail.com> wrote:
>
> > Why do you need a cursor at all? Why not just do
>
> > update mytable
> > set sent_timestamp = current timestamp
> > where sent_timestamp is null;
>
> > and then
>
> > open curs1;
>
> > If you really do need to loop, I think you're better off using a
> > cursor FOR loop (much faster than open...while...fetch), like so:
>
> > FOR l_mytab as c_mytab cursor for
> >    select t_id, t_name
> >    from mytable
> >    where sent_timestamp is null
>
> > DO
> >      update mytable
> >      set sent_timestamp = current timestamp
> >      where t_id = l_mytab.id;--
>
> > end for;--
>
> > As to returning the cursor, the easiest thing to do would be to simply
> > declare it as before and open it after the update, i.e., put the "open
> > curs1;" after the "end for;"
>
> > For something even crazier (and likely faster), you could do this:
>
> > declare curs1 cursor with return for
> > select t_id, t_name
> > from
> > final table
> > (update mytable
> > set sent_timestamp = current timestamp
> > where sent_timestamp is null
> > );--
>
> > open curs1;--
>
> > --Jeff
>
> Thanks, Jeff. I'll give your suggestions a shot. I haven't done
> application development in a long while, so my skills are definitely
> rusty. I knew I was probably missing a fundamental concept here.

No problem--we're all still learning. I've got no issues with cursors
(some of my beast friends....), I just tend to prefer cursor FOR loops
over the "old-fashioned" kind.

Regards,

--Jeff