Job Miller wrote:
From the docs:
http://download.oracle.com/docs/cd/B28359_01/appdev.111/b28395/oci11obj.htm#sthref1617

OCI allows applications to access any of the datatypes found in the Oracle 
database server, including scalar values, collections, and instances of any 
object type. This includes all of the following:

objects
variable-length arrays (varrays)
nested tables (multisets)
references (REFs)
LOBs

Year I leaned that the hard way. Added support for reading objects, varrays and multisets was last year add on to DBD::Oracle.
To take full advantage of Oracle server object capabilities, most applications 
need to do more than just access objects. After an object has been retrieved, 
the application must navigate through references from that object to other 
objects. OCI provides the capability to do this. Through OCI's object 
navigational calls, an application can perform any of the following functions 
on objects:

creating, accessing, locking, deleting, copying, and flushing objects
getting references to the objects and their meta-objects
dynamically getting and setting values of objects' attributes

The OCI navigational calls are discussed in more detail later in this chapter.



This of course could be added to DBD::Oracle the main question being if anyone one really wants to be able to do it. I have found that it is usally much easer to get this form of data into Oracle easy with SQL but a bugger to get it back out.


--- On Thu, 10/23/08, Martin Evans <[EMAIL PROTECTED]> wrote:

From: Martin Evans <[EMAIL PROTECTED]>
Subject: Re: suggestions sought on returning rows from oracle proc and deleting 
them in same proc
To: "dbi-users" <[email protected]>
Date: Thursday, October 23, 2008, 8:40 AM
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.


Yeah that is the example from the pod do you have a very simple one of what you want to return. Really just need the DDL and what you SQL would be like

Cheers
John Scoles
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


Reply via email to