John,
John Scoles wrote:
Martin Evans wrote:
Christian Merz wrote:
Hi Martin,
this is not Perl stuff but Oracle PL/SQL.
I disagree. I'm using DBD::Oracle and I need the values selected in
the procedure returned to perl. The reason it is particularly
applicable to DBD::Oracle is that it would be possible to solve my
problem very easily IF DBD::Oracle supported the returning of oracle
table types without pipelining - it doesn't.
Martin I would write the patch for you on that but I am not sure OCI is
aeven able to do that.
Neither am I - I've asked our resident OCI expert but he has not come
back to me yet.
If you can come up with a very simple (I mean
very simple) test case I will see what I can to tomorrow. (it is my DBD
day) Do other DBD support this sort of type???
I know it allows for the return of ref cursors is this what you want?
I use reference cursors extensively already since the connected user
has no read permission on any tables. The example below for function
f_xxx is one I don't believe you can call from DBD::Oracle.
cheers
John
I wasn't attempting to provoke someone (you?) into adding support for
oracle table/array types to DBD::Oracle but the fact that they may only
be obtained via pipelined functions and you cannot perform DML
statements in a pipelined function meant I had a problem I could not see
a solution to. I only mentioned the lack of support for oracle table
types (without pipelined functions) because it was that which made it a
perl DBD::Oracle issue and not just a pl/sql issue.
I believe the following demonstrates:
CREATE OR REPLACE PACKAGE test IS
type a_t IS TABLE OF integer NOT NULL;
type a_a IS TABLE OF integer NOT NULL INDEX BY BINARY_INTEGER;
FUNCTION f_xxx RETURN a_a;
FUNCTION f_xxx_pipe RETURN a_t PIPELINED;
END;
/
CREATE OR REPLACE PACKAGE BODY test IS
FUNCTION f_xxx RETURN a_a AS
vv a_a;
BEGIN
vv(1) := 1;
vv(2) := 2;
RETURN vv;
END;
FUNCTION f_xxx_pipe RETURN a_t PIPELINED AS
vv a_a;
i integer;
BEGIN
vv := f_xxx();
FOR i IN vv.first .. vv.last LOOP
PIPE row(vv(i));
END LOOP;
END;
END;
/
show errors;
QUIT
perl -e 'use DBI;my $h = DBI->connect("dbi:Oracle:XX","xx","xx");my $s =
$h->prepare(q/select * from table(test.f_xxx_pipe)/);$s->execute;print
DBI::dump_results($s);'
"1"
"2"
2 rows
As far as I know
(http://search.cpan.org/~pythian/DBD-Oracle-1.22/Oracle.pm#Returning_A_Recordset)
there is no way to get that table back from f_xxx other than pipelining.
Don't knock yourself out for my sake on this one; I have an acceptable,
workable alternative. However, if it might be useful for anyone else
that is a different matter.
Martin
--
Martin J. Evans
Easysoft Limited
http://www.easysoft.com
Cheers
Just take your 'get' procedure:
>>>> PROCEDURE get(
>>>> pdt OUT mytable.created%TYPE,
>>>> pcur OUT SYS_REFCURSOR) AS
>>>> BEGIN
>>>> pdt := utc_timestamp();
>>>> OPEN pcur FOR
>>>> SELECT DISTINCT(id) FROM mytable WHERE created <= pdt;
>>>> END;
and try this -untested- code to delete the items immediately after
working with them:
PROCEDURE doit AS
CURSOR curs IS
SELECT * FROM mytable
FOR UPDATE NOWAIT;
BEGIN
FOR rec IN curs
LOOP
EXIT WHEN rec%NOTFOUND;
-- do something useful with rec
this bit needs to be in perl
-- ...
-- delete item
DELETE FROM mytable
WHERE CURRENT OF curs;
END LOOP;
-- COMMIT; -- if not done outside
-- EXCEPTION WHEN OTHERS THEN ROLLBACK;
-- probaly you would write a message in your error_log table ...?
END;
BTW: You should clerify your needs. The following is rather unspecific:
Ok, may be it was not clear enough and that is shown in that your
example does not return any values to perl.
>>>> ... The perl code wants to select the current distinct values of
>>>> the "id" field, do something with them and then all rows which
were
>>>> present when the select was issued need to be deleted (since then
>>>> more rows may have been added which must not be touched)...
SELECT DISTINCT(id) results in sets of IDs rather than single
records. But you can only treat the latter ones in a LOOP.
That is one of the points. I needed the sets of IDs returned to perl
but all the rows that would be scanned to get the set deleted. I also
needed the gathering of the ids and the deletion done in the same proc.
Steve gave me a possible solution.
Thanks for your input anyway.
cu, Christian
Martin