tags:

views:

59

answers:

2

I want to return rows from a select statement within a declare/begin/end block. I can do this in T-SQL but I would like to know how to do it in PL/SQL.

The code looks a bit like the following:

declare
     blah number := 42;
begin
     select *
     from x
     where x.value = blah;
end;
+5  A: 

An anonymous PL/SQL block, like the one you've shown, can't "return" anything. It can interact with the caller by means of bind variables, however.

So the method I would use in this case would be to declare a cursor reference, open it in the PL/SQL block for the desired query, and let the calling application fetch rows from it. In SQLPlus this would look like:

variable rc refcursor

declare
     blah number := 42;
begin
  open :rc for
     select *
     from x
     where x.value = blah;
end;
/

print x

If you recast your PL/SQL as a stored function then it could return values. In this case what you might want to do is create a collection type, fetch all the rows into a variable of that type, and return it:

CREATE TYPE number_table AS TABLE OF NUMBER;

CREATE FUNCTION get_blah_from_x (blah  INTEGER)
  RETURN number_table
  IS
    values  number_table;
  BEGIN
    SELECT id
      BULK COLLECT INTO values
      FROM x
      WHERE x.value = blah;
    RETURN values;
  END;
/
Dave Costa
Thanks - nice answer! What are the performance implications of using a cursor in this case though? I always try to avoid them for their bad performance in T-SQL.
Thomas Bratt
A cursor is nothing more than a reference to a resultset.The performance penalty comes from the roundtrips that are involved between fetching each record. However, every select you invoke against Oracle will be returned to you in the form of a cursor. In .Net they are called DataReaders. When you did not have any perf issues with those, you won't have perf issues with cursors.
Robert Giesecke
A: 

Well, this depends heavily on your data access library.

You can return any SQL-compatible type as a parameter. This includes complex SQL types and collection types. But most libraries are simply not capable of handling Oracle's object types.

Either way, my examples will use these object types:

create type SomeType as object(Field1 VarChar(50));

create type SomeTypeList as table of SomeType;

When your access library can handle object types, you could simply return a list of PL/SQL objects:

begin
  :list := SomeTypeList(SomeType('a'),SomeType('b'),SomeType('c'));
end;

If not, you could hack around it by forcing this list into a select and return its result as a cursor:

declare
  list SomeTypeList;
begin
  list := SomeTypeList(SomeType('a'),SomeType('b'),SomeType('c'));
  open :yourCursor for
    SELECT A
    FROM   table(list);
end;
Robert Giesecke